Removed mcs references
[mono.git] / mcs / mcs / report.cs
1 //
2 // report.cs: report errors and warnings.
3 //
4 // Author: Miguel de Icaza (miguel@ximian.com)
5 //         Marek Safar (marek.safar@seznam.cz)         
6 //
7 // Copyright 2001 Ximian, Inc. (http://www.ximian.com)
8 //
9
10 using System;
11 using System.IO;
12 using System.Text;
13 using System.Collections;
14 using System.Collections.Specialized;
15 using System.Diagnostics;
16 using System.Reflection;
17 using System.Reflection.Emit;
18
19 namespace Mono.CSharp {
20
21         //
22         // Errors and warnings manager
23         //
24         public class Report {
25                 /// <summary>  
26                 ///   Whether errors should be throw an exception
27                 /// </summary>
28                 public bool Fatal;
29                 
30                 /// <summary>  
31                 ///   Whether warnings should be considered errors
32                 /// </summary>
33                 public bool WarningsAreErrors;
34                 ArrayList warnings_as_error;
35                 ArrayList warnings_only;
36
37                 public static int DebugFlags = 0;
38
39                 //
40                 // Keeps track of the warnings that we are ignoring
41                 //
42                 public Hashtable warning_ignore_table;
43
44                 Hashtable warning_regions_table;
45
46                 int warning_level;
47
48                 ReportPrinter printer;
49
50                 int reporting_disabled;
51                 
52                 /// <summary>
53                 /// List of symbols related to reported error/warning. You have to fill it before error/warning is reported.
54                 /// </summary>
55                 ArrayList extra_information = new ArrayList ();
56
57                 // 
58                 // IF YOU ADD A NEW WARNING YOU HAVE TO ADD ITS ID HERE
59                 //
60                 public static readonly int[] AllWarnings = new int[] {
61                         28, 67, 78,
62                         105, 108, 109, 114, 162, 164, 168, 169, 183, 184, 197,
63                         219, 251, 252, 253, 278, 282,
64                         402, 414, 419, 420, 429, 436, 440, 458, 464, 465, 467, 469, 472,
65                         612, 618, 626, 628, 642, 649, 652, 658, 659, 660, 661, 665, 672, 675, 693,
66                         809,
67                         1030, 1058, 1066,
68                         1522, 1570, 1571, 1572, 1573, 1574, 1580, 1581, 1584, 1587, 1589, 1590, 1591, 1592,
69                         1616, 1633, 1634, 1635, 1685, 1690, 1691, 1692,
70                         1700, 1717, 1718, 1720,
71                         1901,
72                         2002, 2023, 2029,
73                         3000, 3001, 3002, 3003, 3005, 3006, 3007, 3008, 3009,
74                         3010, 3011, 3012, 3013, 3014, 3015, 3016, 3017, 3018, 3019,
75                         3021, 3022, 3023, 3024, 3026, 3027
76                 };
77
78                 static Report ()
79                 {
80                         // Just to be sure that binary search is working
81                         Array.Sort (AllWarnings);
82                 }
83
84                 public Report (ReportPrinter printer)
85                 {
86                         if (printer == null)
87                                 throw new ArgumentNullException ("printer");
88
89                         this.printer = printer;
90                         warning_level = 4;
91                 }
92
93                 public void DisableReporting ()
94                 {
95                         ++reporting_disabled;
96                 }
97
98                 public void EnableReporting ()
99                 {
100                         --reporting_disabled;
101                 }
102
103                 public void FeatureIsNotAvailable (Location loc, string feature)
104                 {
105                         string version;
106                         switch (RootContext.Version) {
107                         case LanguageVersion.ISO_1:
108                                 version = "1.0";
109                                 break;
110                         case LanguageVersion.ISO_2:
111                                 version = "2.0";
112                                 break;
113                         case LanguageVersion.V_3:
114                                 version = "3.0";
115                                 break;
116                         default:
117                                 throw new InternalErrorException ("Invalid feature version", RootContext.Version);
118                         }
119
120                         Error (1644, loc,
121                                 "Feature `{0}' cannot be used because it is not part of the C# {1} language specification",
122                                       feature, version);
123                 }
124
125                 public void FeatureIsNotSupported (Location loc, string feature)
126                 {
127                         Error (1644, loc,
128                                 "Feature `{0}' is not supported in Mono mcs1 compiler. Consider using the `gmcs' compiler instead",
129                                 feature);
130                 }
131                 
132                 static bool IsValidWarning (int code)
133                 {       
134                         return Array.BinarySearch (AllWarnings, code) >= 0;
135                 }
136
137                 bool IsWarningEnabled (int code, int level, Location loc)
138                 {
139                         if (WarningLevel < level)
140                                 return false;
141
142                         if (warning_ignore_table != null) {
143                                 if (warning_ignore_table.Contains (code)) {
144                                         return false;
145                                 }
146                         }
147
148                         if (warning_regions_table == null || loc.IsNull)
149                                 return true;
150
151                         WarningRegions regions = (WarningRegions) warning_regions_table [loc.Name];
152                         if (regions == null)
153                                 return true;
154
155                         return regions.IsWarningEnabled (code, loc.Row);
156                 }
157
158                 bool IsWarningAsError (int code)
159                 {
160                         bool is_error = WarningsAreErrors;
161
162                         // Check specific list
163                         if (warnings_as_error != null)
164                                 is_error |= warnings_as_error.Contains (code);
165
166                         // Ignore excluded warnings
167                         if (warnings_only != null && warnings_only.Contains (code))
168                                 is_error = false;
169
170                         return is_error;
171                 }
172                         
173                 public void RuntimeMissingSupport (Location loc, string feature) 
174                 {
175                         Error (-88, loc, "Your .NET Runtime does not support `{0}'. Please use the latest Mono runtime instead.", feature);
176                 }
177
178                 /// <summary>
179                 /// In most error cases is very useful to have information about symbol that caused the error.
180                 /// Call this method before you call Report.Error when it makes sense.
181                 /// </summary>
182                 public void SymbolRelatedToPreviousError (Location loc, string symbol)
183                 {
184                         SymbolRelatedToPreviousError (loc.ToString (), symbol);
185                 }
186
187                 public void SymbolRelatedToPreviousError (MemberInfo mi)
188                 {
189                         if (reporting_disabled > 0 || !printer.HasRelatedSymbolSupport)
190                                 return;
191
192                         Type dt = TypeManager.DropGenericTypeArguments (mi.DeclaringType);
193                         if (TypeManager.IsDelegateType (dt)) {
194                                 SymbolRelatedToPreviousError (dt);
195                                 return;
196                         }                       
197                         
198                         DeclSpace temp_ds = TypeManager.LookupDeclSpace (dt);
199                         if (temp_ds == null) {
200                                 SymbolRelatedToPreviousError (dt.Assembly.Location, TypeManager.GetFullNameSignature (mi));
201                         } else {
202                                 MethodBase mb = mi as MethodBase;
203                                 if (mb != null) {
204                                         mb = TypeManager.DropGenericMethodArguments (mb);
205                                         IMethodData md = TypeManager.GetMethod (mb);
206                                         if (md != null)
207                                                 SymbolRelatedToPreviousError (md.Location, md.GetSignatureForError ());
208
209                                         return;
210                                 }
211
212                                 // FIXME: Completely wrong, it has to use FindMembers
213                                 MemberCore mc = temp_ds.GetDefinition (mi.Name);
214                                 if (mc != null)
215                                         SymbolRelatedToPreviousError (mc);
216                         }
217                 }
218
219                 public void SymbolRelatedToPreviousError (MemberCore mc)
220                 {
221                         SymbolRelatedToPreviousError (mc.Location, mc.GetSignatureForError ());
222                 }
223
224                 public void SymbolRelatedToPreviousError (Type type)
225                 {
226                         if (reporting_disabled > 0 || !printer.HasRelatedSymbolSupport)
227                                 return;
228
229                         type = TypeManager.DropGenericTypeArguments (type);
230
231                         if (TypeManager.IsGenericParameter (type)) {
232                                 TypeParameter tp = TypeManager.LookupTypeParameter (type);
233                                 if (tp != null) {
234                                         SymbolRelatedToPreviousError (tp.Location, "");
235                                         return;
236                                 }
237                         }
238
239                         if (type is TypeBuilder) {
240                                 DeclSpace temp_ds = TypeManager.LookupDeclSpace (type);
241                                 SymbolRelatedToPreviousError (temp_ds.Location, TypeManager.CSharpName (type));
242                         } else if (TypeManager.HasElementType (type)) {
243                                 SymbolRelatedToPreviousError (TypeManager.GetElementType (type));
244                         } else {
245                                 SymbolRelatedToPreviousError (type.Assembly.Location, TypeManager.CSharpName (type));
246                         }
247                 }
248
249                 void SymbolRelatedToPreviousError (string loc, string symbol)
250                 {
251                         string msg = String.Format ("{0} (Location of the symbol related to previous ", loc);
252                         if (extra_information.Contains (msg))
253                                 return;
254
255                         extra_information.Add (msg);
256                 }
257
258                 public void AddWarningAsError (string warningId)
259                 {
260                         int id;
261                         try {
262                                 id = int.Parse (warningId);
263                         } catch {
264                                 id = -1;
265                         }
266
267                         if (!CheckWarningCode (id, warningId, Location.Null))
268                                 return;
269
270                         if (warnings_as_error == null)
271                                 warnings_as_error = new ArrayList ();
272                         
273                         warnings_as_error.Add (id);
274                 }
275
276                 public void RemoveWarningAsError (string warningId)
277                 {
278                         int id;
279                         try {
280                                 id = int.Parse (warningId);
281                         } catch {
282                                 id = -1;
283                         }
284
285                         if (!CheckWarningCode (id, warningId, Location.Null))
286                                 return;
287
288                         if (warnings_only == null)
289                                 warnings_only = new ArrayList ();
290
291                         warnings_only.Add (id);
292                 }
293
294                 public bool CheckWarningCode (int code, Location loc)
295                 {
296                         return CheckWarningCode (code, code.ToString (), loc);
297                 }
298
299                 public bool CheckWarningCode (int code, string scode, Location loc)
300                 {
301                         if (IsValidWarning (code))
302                                 return true;
303
304                         Warning (1691, 1, loc, "`{0}' is not a valid warning number", scode);
305                         return false;
306                 }
307
308                 public void ExtraInformation (Location loc, string msg)
309                 {
310                         extra_information.Add (String.Format ("{0} {1}", loc, msg));
311                 }
312
313                 public WarningRegions RegisterWarningRegion (Location location)
314                 {
315                         if (warning_regions_table == null)
316                                 warning_regions_table = new Hashtable ();
317
318                         WarningRegions regions = (WarningRegions)warning_regions_table [location.Name];
319                         if (regions == null) {
320                                 regions = new WarningRegions ();
321                                 warning_regions_table.Add (location.Name, regions);
322                         }
323                         return regions;
324                 }
325
326                 public void Warning (int code, int level, Location loc, string message)
327                 {
328                         if (reporting_disabled > 0)
329                                 return;
330
331                         if (!IsWarningEnabled (code, level, loc))
332                                 return;
333
334                         AbstractMessage msg;
335                         if (IsWarningAsError (code))
336                                 msg = new ErrorMessage (code, loc, message, extra_information);
337                         else
338                                 msg = new WarningMessage (code, loc, message, extra_information);
339
340                         extra_information.Clear ();
341                         printer.Print (msg);
342                 }
343
344                 public void Warning (int code, int level, Location loc, string format, string arg)
345                 {
346                         Warning (code, level, loc, String.Format (format, arg));
347                 }
348
349                 public void Warning (int code, int level, Location loc, string format, string arg1, string arg2)
350                 {
351                         Warning (code, level, loc, String.Format (format, arg1, arg2));
352                 }
353
354                 public void Warning (int code, int level, Location loc, string format, params object[] args)
355                 {
356                         Warning (code, level, loc, String.Format (format, args));
357                 }
358
359                 public void Warning (int code, int level, string message)
360                 {
361                         Warning (code, level, Location.Null, message);
362                 }
363
364                 public void Warning (int code, int level, string format, string arg)
365                 {
366                         Warning (code, level, Location.Null, format, arg);
367                 }
368
369                 public void Warning (int code, int level, string format, string arg1, string arg2)
370                 {
371                         Warning (code, level, Location.Null, format, arg1, arg2);
372                 }
373
374                 public void Warning (int code, int level, string format, params string[] args)
375                 {
376                         Warning (code, level, Location.Null, String.Format (format, args));
377                 }
378
379                 //
380                 // Warnings encountered so far
381                 //
382                 public int Warnings {
383                         get { return printer.WarningsCount; }
384                 }
385
386                 public void Error (int code, Location loc, string error)
387                 {
388                         if (reporting_disabled > 0)
389                                 return;
390
391                         ErrorMessage msg = new ErrorMessage (code, loc, error, extra_information);
392                         extra_information.Clear ();
393
394                         printer.Print (msg);
395
396                         if (Fatal)
397                                 throw new Exception (msg.Text);
398                 }
399
400                 public void Error (int code, Location loc, string format, string arg)
401                 {
402                         Error (code, loc, String.Format (format, arg));
403                 }
404
405                 public void Error (int code, Location loc, string format, string arg1, string arg2)
406                 {
407                         Error (code, loc, String.Format (format, arg1, arg2));
408                 }
409
410                 public void Error (int code, Location loc, string format, params object[] args)
411                 {
412                         Error (code, loc, String.Format (format, args));
413                 }
414
415                 public void Error (int code, string error)
416                 {
417                         Error (code, Location.Null, error);
418                 }
419
420                 public void Error (int code, string format, string arg)
421                 {
422                         Error (code, Location.Null, format, arg);
423                 }
424
425                 public void Error (int code, string format, string arg1, string arg2)
426                 {
427                         Error (code, Location.Null, format, arg1, arg2);
428                 }
429
430                 public void Error (int code, string format, params string[] args)
431                 {
432                         Error (code, Location.Null, String.Format (format, args));
433                 }
434
435                 //
436                 // Errors encountered so far
437                 //
438                 public int Errors {
439                         get { return printer.ErrorsCount; }
440                 }
441
442                 public ReportPrinter Printer {
443                         get { return printer; }
444                 }
445
446                 public void SetIgnoreWarning (int code)
447                 {
448                         if (warning_ignore_table == null)
449                                 warning_ignore_table = new Hashtable ();
450
451                         warning_ignore_table [code] = true;
452                 }
453
454                 public ReportPrinter SetPrinter (ReportPrinter printer)
455                 {
456                         ReportPrinter old = this.printer;
457                         this.printer = printer;
458                         return old;
459                 }
460                 
461                 public int WarningLevel {
462                         get {
463                                 return warning_level;
464                         }
465                         set {
466                                 warning_level = value;
467                         }
468                 }
469
470                 [Conditional ("MCS_DEBUG")]
471                 static public void Debug (string message, params object[] args)
472                 {
473                         Debug (4, message, args);
474                 }
475                         
476                 [Conditional ("MCS_DEBUG")]
477                 static public void Debug (int category, string message, params object[] args)
478                 {
479                         if ((category & DebugFlags) == 0)
480                                 return;
481
482                         StringBuilder sb = new StringBuilder (message);
483
484                         if ((args != null) && (args.Length > 0)) {
485                                 sb.Append (": ");
486
487                                 bool first = true;
488                                 foreach (object arg in args) {
489                                         if (first)
490                                                 first = false;
491                                         else
492                                                 sb.Append (", ");
493                                         if (arg == null)
494                                                 sb.Append ("null");
495                                         else if (arg is ICollection)
496                                                 sb.Append (PrintCollection ((ICollection) arg));
497                                         else
498                                                 sb.Append (arg);
499                                 }
500                         }
501
502                         Console.WriteLine (sb.ToString ());
503                 }
504
505                 static public string PrintCollection (ICollection collection)
506                 {
507                         StringBuilder sb = new StringBuilder ();
508
509                         sb.Append (collection.GetType ());
510                         sb.Append ("(");
511
512                         bool first = true;
513                         foreach (object o in collection) {
514                                 if (first)
515                                         first = false;
516                                 else
517                                         sb.Append (", ");
518                                 sb.Append (o);
519                         }
520
521                         sb.Append (")");
522                         return sb.ToString ();
523                 }
524         }
525
526         public abstract class AbstractMessage
527         {
528                 readonly string[] extra_info;
529                 protected readonly int code;
530                 protected readonly Location location;
531                 readonly string message;
532
533                 protected AbstractMessage (int code, Location loc, string msg, ArrayList extraInfo)
534                 {
535                         this.code = code;
536                         if (code < 0)
537                                 this.code = 8000 - code;
538
539                         this.location = loc;
540                         this.message = msg;
541                         if (extraInfo.Count != 0) {
542                                 this.extra_info = (string[])extraInfo.ToArray (typeof (string));
543                         }
544                 }
545
546                 protected AbstractMessage (AbstractMessage aMsg)
547                 {
548                         this.code = aMsg.code;
549                         this.location = aMsg.location;
550                         this.message = aMsg.message;
551                         this.extra_info = aMsg.extra_info;
552                 }
553
554                 public int Code {
555                         get { return code; }
556                 }
557
558                 public override bool Equals (object obj)
559                 {
560                         AbstractMessage msg = obj as AbstractMessage;
561                         if (msg == null)
562                                 return false;
563
564                         return code == msg.code && location.Equals (msg.location) && message == msg.message;
565                 }
566
567                 public override int GetHashCode ()
568                 {
569                         return code.GetHashCode ();
570                 }
571
572                 public abstract bool IsWarning { get; }
573
574                 public Location Location {
575                         get { return location; }
576                 }
577
578                 public abstract string MessageType { get; }
579
580                 public string[] RelatedSymbols {
581                         get { return extra_info; }
582                 }
583
584                 public string Text {
585                         get { return message; }
586                 }
587         }
588
589         sealed class WarningMessage : AbstractMessage
590         {
591                 public WarningMessage (int code, Location loc, string message, ArrayList extra_info)
592                         : base (code, loc, message, extra_info)
593                 {
594                 }
595
596                 public override bool IsWarning {
597                         get { return true; }
598                 }
599
600                 public override string MessageType {
601                         get {
602                                 return "warning";
603                         }
604                 }
605         }
606
607         sealed class ErrorMessage : AbstractMessage
608         {
609                 public ErrorMessage (int code, Location loc, string message, ArrayList extraInfo)
610                         : base (code, loc, message, extraInfo)
611                 {
612                 }
613
614                 public ErrorMessage (AbstractMessage aMsg)
615                         : base (aMsg)
616                 {
617                 }
618
619                 public override bool IsWarning {
620                         get { return false; }
621                 }
622
623                 public override string MessageType {
624                         get {
625                                 return "error";
626                         }
627                 }
628         }
629
630         //
631         // Generic base for any message writer
632         //
633         public abstract class ReportPrinter
634         {
635                 /// <summary>  
636                 ///   Whether to dump a stack trace on errors. 
637                 /// </summary>
638                 public bool Stacktrace;
639                 
640                 int warnings, errors;
641
642                 public int WarningsCount {
643                         get { return warnings; }
644                 }
645                 
646                 public int ErrorsCount {
647                         get { return errors; }
648                 }
649
650                 protected virtual string FormatText (string txt)
651                 {
652                         return txt;
653                 }
654
655                 //
656                 // When (symbols related to previous ...) can be used
657                 //
658                 public virtual bool HasRelatedSymbolSupport {
659                         get { return true; }
660                 }
661
662                 public virtual void Print (AbstractMessage msg)
663                 {
664                         if (msg.IsWarning)
665                                 ++warnings;
666                         else
667                                 ++errors;
668                 }
669
670                 protected void Print (AbstractMessage msg, TextWriter output)
671                 {
672                         StringBuilder txt = new StringBuilder ();
673                         if (!msg.Location.IsNull) {
674                                 txt.Append (msg.Location.ToString ());
675                                 txt.Append (" ");
676                         }
677
678                         txt.AppendFormat ("{0} CS{1:0000}: {2}", msg.MessageType, msg.Code, msg.Text);
679
680                         if (!msg.IsWarning)
681                                 output.WriteLine (FormatText (txt.ToString ()));
682                         else
683                                 output.WriteLine (txt.ToString ());
684
685                         if (msg.RelatedSymbols != null) {
686                                 foreach (string s in msg.RelatedSymbols)
687                                         output.WriteLine (s + msg.MessageType + ")");
688                         }
689                 }
690         }
691
692         //
693         // Default message recorder, it uses two types of message groups.
694         // Common messages: messages reported in all sessions.
695         // Merged messages: union of all messages in all sessions. 
696         //
697         // Used by the Lambda expressions to compile the code with various
698         // parameter values, or by attribute resolver
699         //
700         class SessionReportPrinter : ReportPrinter
701         {
702                 ArrayList session_messages;
703                 //
704                 // A collection of exactly same messages reported in all sessions
705                 //
706                 ArrayList common_messages;
707
708                 //
709                 // A collection of unique messages reported in all sessions
710                 //
711                 ArrayList merged_messages;
712
713                 public override void Print (AbstractMessage msg)
714                 {
715                         //
716                         // This line is useful when debugging recorded messages
717                         //
718                         // Console.WriteLine ("RECORDING: {0} {1} {2}", code, location, message);
719
720                         if (session_messages == null)
721                                 session_messages = new ArrayList ();
722
723                         session_messages.Add (msg);
724
725                         base.Print (msg);
726                 }
727
728                 public void EndSession ()
729                 {
730                         if (session_messages == null)
731                                 return;
732
733                         //
734                         // Handles the first session
735                         //
736                         if (common_messages == null) {
737                                 common_messages = new ArrayList (session_messages);
738                                 merged_messages = session_messages;
739                                 session_messages = null;
740                                 return;
741                         }
742
743                         //
744                         // Store common messages if any
745                         //
746                         for (int i = 0; i < common_messages.Count; ++i) {
747                                 AbstractMessage cmsg = (AbstractMessage) common_messages[i];
748                                 bool common_msg_found = false;
749                                 foreach (AbstractMessage msg in session_messages) {
750                                         if (cmsg.Equals (msg)) {
751                                                 common_msg_found = true;
752                                                 break;
753                                         }
754                                 }
755
756                                 if (!common_msg_found)
757                                         common_messages.RemoveAt (i);
758                         }
759
760                         //
761                         // Merge session and previous messages
762                         //
763                         for (int i = 0; i < session_messages.Count; ++i) {
764                                 AbstractMessage msg = (AbstractMessage) session_messages[i];
765                                 bool msg_found = false;
766                                 for (int ii = 0; ii < merged_messages.Count; ++ii) {
767                                         if (msg.Equals (merged_messages[ii])) {
768                                                 msg_found = true;
769                                                 break;
770                                         }
771                                 }
772
773                                 if (!msg_found)
774                                         merged_messages.Add (msg);
775                         }
776                 }
777
778                 public bool IsEmpty {
779                         get {
780                                 return merged_messages == null && common_messages == null;
781                         }
782                 }
783
784                 //
785                 // Prints collected messages, common messages have a priority
786                 //
787                 public bool Merge (ReportPrinter dest)
788                 {
789                         ArrayList messages_to_print = merged_messages;
790                         if (common_messages != null && common_messages.Count > 0) {
791                                 messages_to_print = common_messages;
792                         }
793
794                         if (messages_to_print == null)
795                                 return false;
796
797                         foreach (AbstractMessage msg in messages_to_print)
798                                 dest.Print (msg);
799
800                         return true;
801                 }
802         }
803
804         class StreamReportPrinter : ReportPrinter
805         {
806                 readonly TextWriter writer;
807
808                 public StreamReportPrinter (TextWriter writer)
809                 {
810                         this.writer = writer;
811                 }
812
813                 public override void Print (AbstractMessage msg)
814                 {
815                         Print (msg, writer);
816                         base.Print (msg);
817                 }
818         }
819
820         class ConsoleReportPrinter : StreamReportPrinter
821         {
822                 static readonly string prefix, postfix;
823
824                 static ConsoleReportPrinter ()
825                 {
826                         string term = Environment.GetEnvironmentVariable ("TERM");
827                         bool xterm_colors = false;
828                         
829                         switch (term){
830                         case "xterm":
831                         case "rxvt":
832                         case "rxvt-unicode": 
833                                 if (Environment.GetEnvironmentVariable ("COLORTERM") != null){
834                                         xterm_colors = true;
835                                 }
836                                 break;
837
838                         case "xterm-color":
839                                 xterm_colors = true;
840                                 break;
841                         }
842                         if (!xterm_colors)
843                                 return;
844
845                         if (!(UnixUtils.isatty (1) && UnixUtils.isatty (2)))
846                                 return;
847                         
848                         string config = Environment.GetEnvironmentVariable ("MCS_COLORS");
849                         if (config == null){
850                                 config = "errors=red";
851                                 //config = "brightwhite,red";
852                         }
853
854                         if (config == "disable")
855                                 return;
856
857                         if (!config.StartsWith ("errors="))
858                                 return;
859
860                         config = config.Substring (7);
861                         
862                         int p = config.IndexOf (",");
863                         if (p == -1)
864                                 prefix = GetForeground (config);
865                         else
866                                 prefix = GetBackground (config.Substring (p+1)) + GetForeground (config.Substring (0, p));
867                         postfix = "\x001b[0m";
868                 }
869
870                 public ConsoleReportPrinter ()
871                         : base (Console.Error)
872                 {
873                 }
874
875                 public ConsoleReportPrinter (TextWriter writer)
876                         : base (writer)
877                 {
878                 }
879
880                 static int NameToCode (string s)
881                 {
882                         switch (s) {
883                         case "black":
884                                 return 0;
885                         case "red":
886                                 return 1;
887                         case "green":
888                                 return 2;
889                         case "yellow":
890                                 return 3;
891                         case "blue":
892                                 return 4;
893                         case "magenta":
894                                 return 5;
895                         case "cyan":
896                                 return 6;
897                         case "grey":
898                         case "white":
899                                 return 7;
900                         }
901                         return 7;
902                 }
903
904                 //
905                 // maps a color name to its xterm color code
906                 //
907                 static string GetForeground (string s)
908                 {
909                         string highcode;
910
911                         if (s.StartsWith ("bright")) {
912                                 highcode = "1;";
913                                 s = s.Substring (6);
914                         } else
915                                 highcode = "";
916
917                         return "\x001b[" + highcode + (30 + NameToCode (s)).ToString () + "m";
918                 }
919
920                 static string GetBackground (string s)
921                 {
922                         return "\x001b[" + (40 + NameToCode (s)).ToString () + "m";
923                 }
924
925                 protected override string FormatText (string txt)
926                 {
927                         if (prefix != null)
928                                 return prefix + txt + postfix;
929
930                         return txt;
931                 }
932
933                 static string FriendlyStackTrace (StackTrace t)
934                 {               
935                         StringBuilder sb = new StringBuilder ();
936                         
937                         bool foundUserCode = false;
938                         
939                         for (int i = 0; i < t.FrameCount; i++) {
940                                 StackFrame f = t.GetFrame (i);
941                                 MethodBase mb = f.GetMethod ();
942                                 
943                                 if (!foundUserCode && mb.ReflectedType == typeof (Report))
944                                         continue;
945                                 
946                                 foundUserCode = true;
947                                 
948                                 sb.Append ("\tin ");
949                                 
950                                 if (f.GetFileLineNumber () > 0)
951                                         sb.AppendFormat ("(at {0}:{1}) ", f.GetFileName (), f.GetFileLineNumber ());
952                                 
953                                 sb.AppendFormat ("{0}.{1} (", mb.ReflectedType.Name, mb.Name);
954                                 
955                                 bool first = true;
956                                 foreach (ParameterInfo pi in mb.GetParameters ()) {
957                                         if (!first)
958                                                 sb.Append (", ");
959                                         first = false;
960                                         
961                                         sb.Append (TypeManager.CSharpName (pi.ParameterType));
962                                 }
963                                 sb.Append (")\n");
964                         }
965         
966                         return sb.ToString ();
967                 }
968
969                 public override void Print (AbstractMessage msg)
970                 {
971                         base.Print (msg);
972
973                         if (Stacktrace)
974                                 Console.WriteLine (FriendlyStackTrace (new StackTrace (true)));
975                 }
976
977                 public static string FriendlyStackTrace (Exception e)
978                 {
979                         return FriendlyStackTrace (new StackTrace (e, true));
980                 }
981
982                 public static void StackTrace ()
983                 {
984                         Console.WriteLine (FriendlyStackTrace (new StackTrace (true)));
985                 }
986         }
987
988         public enum TimerType {
989                 FindMembers     = 0,
990                 TcFindMembers   = 1,
991                 MemberLookup    = 2,
992                 CachedLookup    = 3,
993                 CacheInit       = 4,
994                 MiscTimer       = 5,
995                 CountTimers     = 6
996         }
997
998         public enum CounterType {
999                 FindMembers     = 0,
1000                 MemberCache     = 1,
1001                 MiscCounter     = 2,
1002                 CountCounters   = 3
1003         }
1004
1005         public class Timer
1006         {
1007                 static DateTime[] timer_start;
1008                 static TimeSpan[] timers;
1009                 static long[] timer_counters;
1010                 static long[] counters;
1011
1012                 static Timer ()
1013                 {
1014                         timer_start = new DateTime [(int) TimerType.CountTimers];
1015                         timers = new TimeSpan [(int) TimerType.CountTimers];
1016                         timer_counters = new long [(int) TimerType.CountTimers];
1017                         counters = new long [(int) CounterType.CountCounters];
1018
1019                         for (int i = 0; i < (int) TimerType.CountTimers; i++) {
1020                                 timer_start [i] = DateTime.Now;
1021                                 timers [i] = TimeSpan.Zero;
1022                         }
1023                 }
1024
1025                 [Conditional("TIMER")]
1026                 static public void IncrementCounter (CounterType which)
1027                 {
1028                         ++counters [(int) which];
1029                 }
1030
1031                 [Conditional("TIMER")]
1032                 static public void StartTimer (TimerType which)
1033                 {
1034                         timer_start [(int) which] = DateTime.Now;
1035                 }
1036
1037                 [Conditional("TIMER")]
1038                 static public void StopTimer (TimerType which)
1039                 {
1040                         timers [(int) which] += DateTime.Now - timer_start [(int) which];
1041                         ++timer_counters [(int) which];
1042                 }
1043
1044                 [Conditional("TIMER")]
1045                 static public void ShowTimers ()
1046                 {
1047                         ShowTimer (TimerType.FindMembers, "- FindMembers timer");
1048                         ShowTimer (TimerType.TcFindMembers, "- TypeContainer.FindMembers timer");
1049                         ShowTimer (TimerType.MemberLookup, "- MemberLookup timer");
1050                         ShowTimer (TimerType.CachedLookup, "- CachedLookup timer");
1051                         ShowTimer (TimerType.CacheInit, "- Cache init");
1052                         ShowTimer (TimerType.MiscTimer, "- Misc timer");
1053
1054                         ShowCounter (CounterType.FindMembers, "- Find members");
1055                         ShowCounter (CounterType.MemberCache, "- Member cache");
1056                         ShowCounter (CounterType.MiscCounter, "- Misc counter");
1057                 }
1058
1059                 static public void ShowCounter (CounterType which, string msg)
1060                 {
1061                         Console.WriteLine ("{0} {1}", counters [(int) which], msg);
1062                 }
1063
1064                 static public void ShowTimer (TimerType which, string msg)
1065                 {
1066                         Console.WriteLine (
1067                                 "[{0:00}:{1:000}] {2} (used {3} times)",
1068                                 (int) timers [(int) which].TotalSeconds,
1069                                 timers [(int) which].Milliseconds, msg,
1070                                 timer_counters [(int) which]);
1071                 }
1072         }
1073
1074         public class InternalErrorException : Exception {
1075                 public InternalErrorException (MemberCore mc, Exception e)
1076                         : base (mc.Location + " " + mc.GetSignatureForError (), e)
1077                 {
1078                 }
1079
1080                 public InternalErrorException ()
1081                         : base ("Internal error")
1082                 {
1083                 }
1084
1085                 public InternalErrorException (string message)
1086                         : base (message)
1087                 {
1088                 }
1089
1090                 public InternalErrorException (string message, params object[] args)
1091                         : base (String.Format (message, args))
1092                 { }
1093                 
1094                 public InternalErrorException (Exception e, Location loc)
1095                         : base (loc.ToString (), e)
1096                 {
1097                 }
1098         }
1099
1100         /// <summary>
1101         /// Handles #pragma warning
1102         /// </summary>
1103         public class WarningRegions {
1104
1105                 abstract class PragmaCmd
1106                 {
1107                         public int Line;
1108
1109                         protected PragmaCmd (int line)
1110                         {
1111                                 Line = line;
1112                         }
1113
1114                         public abstract bool IsEnabled (int code, bool previous);
1115                 }
1116                 
1117                 class Disable : PragmaCmd
1118                 {
1119                         int code;
1120                         public Disable (int line, int code)
1121                                 : base (line)
1122                         {
1123                                 this.code = code;
1124                         }
1125
1126                         public override bool IsEnabled (int code, bool previous)
1127                         {
1128                                 return this.code == code ? false : previous;
1129                         }
1130                 }
1131
1132                 class DisableAll : PragmaCmd
1133                 {
1134                         public DisableAll (int line)
1135                                 : base (line) {}
1136
1137                         public override bool IsEnabled(int code, bool previous)
1138                         {
1139                                 return false;
1140                         }
1141                 }
1142
1143                 class Enable : PragmaCmd
1144                 {
1145                         int code;
1146                         public Enable (int line, int code)
1147                                 : base (line)
1148                         {
1149                                 this.code = code;
1150                         }
1151
1152                         public override bool IsEnabled(int code, bool previous)
1153                         {
1154                                 return this.code == code ? true : previous;
1155                         }
1156                 }
1157
1158                 class EnableAll : PragmaCmd
1159                 {
1160                         public EnableAll (int line)
1161                                 : base (line) {}
1162
1163                         public override bool IsEnabled(int code, bool previous)
1164                         {
1165                                 return true;
1166                         }
1167                 }
1168
1169
1170                 ArrayList regions = new ArrayList ();
1171
1172                 public void WarningDisable (int line)
1173                 {
1174                         regions.Add (new DisableAll (line));
1175                 }
1176
1177                 public void WarningDisable (Location location, int code, Report Report)
1178                 {
1179                         if (Report.CheckWarningCode (code, location))
1180                                 regions.Add (new Disable (location.Row, code));
1181                 }
1182
1183                 public void WarningEnable (int line)
1184                 {
1185                         regions.Add (new EnableAll (line));
1186                 }
1187
1188                 public void WarningEnable (Location location, int code, Report Report)
1189                 {
1190                         if (Report.CheckWarningCode (code, location))
1191                                 regions.Add (new Enable (location.Row, code));
1192                 }
1193
1194                 public bool IsWarningEnabled (int code, int src_line)
1195                 {
1196                         bool result = true;
1197                         foreach (PragmaCmd pragma in regions) {
1198                                 if (src_line < pragma.Line)
1199                                         break;
1200
1201                                 result = pragma.IsEnabled (code, result);
1202                         }
1203                         return result;
1204                 }
1205         }
1206 }