2003-04-30 Gonzalo Paniagua Javier <gonzalo@ximian.com>
authorGonzalo Paniagua Javier <gonzalo.mono@gmail.com>
Wed, 30 Apr 2003 04:56:01 +0000 (04:56 -0000)
committerGonzalo Paniagua Javier <gonzalo.mono@gmail.com>
Wed, 30 Apr 2003 04:56:01 +0000 (04:56 -0000)
* AspComponentFoundry.cs: simplified it a lot by using Type and Assembly
instead of their names.

* AspElements.cs: removed. No longer needed.

* AspGenerator.cs: this file is now in charge of interfacing between
the parser and the compiler. It manages the creation of the
ControlBuilder tree and the compilation of the CodeDOM tree.

* AspParser.cs: tag handling is simpler now.  Instead of a whole bunch
of different Types, tags are just and id and a set of attributes.
Implement ILocation interface.

* AspTokenizer.cs: added a few methods to help the parser implementing
ILocation.

* BaseCompiler.cs: handles the portions of the CodeDOM tree that are
common to appliaction, page and user control, including the actual
compilation and error handling.

* CSCompiler.cs: compiles C# files using CodeDOM interfaces.

* CachingCompiler.cs: simplified to use the new interfaces.

* CompilationException.cs: it's now using CompilationResult to report
errors.

* CompilationResult.cs: Removed file.

* Directive.cs: to check for the validity of a directive.

* GlobalAsaxCompiler.cs: simplified a lot, as most of the work is done
in BaseCompiler.

* ILocation.cs: interface used to now the exact place where a parse
error happens.

* PageCompiler.cs: generates a couple of methods that are only used in
pages.

* ParseException.cs: use the ILocation interface.

* TagAttributes.cs: handles the attributes of the tags parsed.

* TagType.cs: an enum for the different kinds of tags.

* TemplateControlCompiler.cs: this is the one that does most of the
conversion from teh ControlBuilder tree into a CodeDOM tree.

* UserControlCompiler.cs: simplified as most of the work is done in
its base classes.

* WebServiceCompiler.cs: dummy.

svn path=/trunk/mcs/; revision=14140

21 files changed:
mcs/class/System.Web/System.Web.Compilation/AspComponentFoundry.cs
mcs/class/System.Web/System.Web.Compilation/AspElements.cs [deleted file]
mcs/class/System.Web/System.Web.Compilation/AspGenerator.cs
mcs/class/System.Web/System.Web.Compilation/AspParser.cs
mcs/class/System.Web/System.Web.Compilation/AspTokenizer.cs
mcs/class/System.Web/System.Web.Compilation/BaseCompiler.cs
mcs/class/System.Web/System.Web.Compilation/CSCompiler.cs [new file with mode: 0644]
mcs/class/System.Web/System.Web.Compilation/CachingCompiler.cs
mcs/class/System.Web/System.Web.Compilation/ChangeLog
mcs/class/System.Web/System.Web.Compilation/CompilationException.cs
mcs/class/System.Web/System.Web.Compilation/CompilationResult.cs [deleted file]
mcs/class/System.Web/System.Web.Compilation/Directive.cs [new file with mode: 0644]
mcs/class/System.Web/System.Web.Compilation/GlobalAsaxCompiler.cs
mcs/class/System.Web/System.Web.Compilation/ILocation.cs [new file with mode: 0644]
mcs/class/System.Web/System.Web.Compilation/PageCompiler.cs
mcs/class/System.Web/System.Web.Compilation/ParseException.cs
mcs/class/System.Web/System.Web.Compilation/TagAttributes.cs [new file with mode: 0644]
mcs/class/System.Web/System.Web.Compilation/TagType.cs [new file with mode: 0644]
mcs/class/System.Web/System.Web.Compilation/TemplateControlCompiler.cs [new file with mode: 0644]
mcs/class/System.Web/System.Web.Compilation/UserControlCompiler.cs
mcs/class/System.Web/System.Web.Compilation/WebServiceCompiler.cs

index a0c4b3579dc0e1b590d4d81500b80b91ecb40206..abc43a3e94bb113f9a95197c21d75433baecab1b 100644 (file)
@@ -4,7 +4,7 @@
 // Authors:\r
 //     Gonzalo Paniagua Javier (gonzalo@ximian.com)\r
 //\r
-// (C) 2002 Ximian, Inc (http://www.ximian.com)\r
+// (C) 2002,2003 Ximian, Inc (http://www.ximian.com)\r
 //\r
 using System;\r
 using System.Collections;\r
@@ -22,18 +22,9 @@ namespace System.Web.Compilation
                        foundries = new Hashtable (CaseInsensitiveHashCodeProvider.Default,\r
                                                   CaseInsensitiveComparer.Default);\r
 \r
-                       RegisterFoundry ("asp", "System.Web", "System.Web.UI.WebControls");\r
-                       RegisterFoundry ("", "object", "System.Web", "System.Web.UI", "ObjectTag");\r
-               }\r
-\r
-               // TODO: don't forget to remove this method...\r
-               public AspComponent MakeAspComponent (string foundryName, string componentName, Tag tag)\r
-               {\r
-                       Foundry foundry = foundries [foundryName] as Foundry;\r
-                       if (foundry == null)\r
-                               throw new ApplicationException ("Foundry not found: " + foundryName);\r
-\r
-                       return new AspComponent (tag, foundry.GetType (componentName));\r
+                       Assembly sw = typeof (AspComponentFoundry).Assembly;\r
+                       RegisterFoundry ("asp", sw, "System.Web.UI.WebControls");\r
+                       RegisterFoundry ("", "object", typeof (System.Web.UI.ObjectTag));\r
                }\r
 \r
                public Type GetComponentType (string foundryName, string tag)\r
@@ -46,20 +37,18 @@ namespace System.Web.Compilation
                }\r
 \r
                public void RegisterFoundry (string foundryName,\r
-                                               string assemblyName,\r
+                                               Assembly assembly,\r
                                                string nameSpace)\r
                {\r
-                       AssemblyFoundry foundry = new AssemblyFoundry (assemblyName, nameSpace);\r
+                       AssemblyFoundry foundry = new AssemblyFoundry (assembly, nameSpace);\r
                        InternalRegister (foundryName, foundry);\r
                }\r
 \r
                public void RegisterFoundry (string foundryName,\r
                                                string tagName,\r
-                                               string assemblyName,\r
-                                               string nameSpace,\r
-                                               string typeName)\r
+                                               Type type)\r
                {\r
-                       TagNameFoundry foundry = new TagNameFoundry (assemblyName, tagName, nameSpace, typeName);\r
+                       TagNameFoundry foundry = new TagNameFoundry (tagName, type);\r
                        InternalRegister (foundryName, foundry);\r
                }\r
 \r
@@ -87,54 +76,25 @@ namespace System.Web.Compilation
                abstract class Foundry\r
                {\r
                        public abstract Type GetType (string componentName);\r
-\r
-                       public Assembly LoadAssembly (string assemblyName)\r
-                       {\r
-                               Assembly assembly = null;\r
-                               try {\r
-                                       assembly = Assembly.LoadFrom (Path.GetFullPath (assemblyName));\r
-                               } catch {\r
-                                       string partialName = assemblyName;\r
-                                       if (String.Compare (Path.GetExtension (partialName), ".dll", true) == 0)\r
-                                               partialName = Path.GetFileNameWithoutExtension (assemblyName);\r
-\r
-                                       assembly = Assembly.LoadWithPartialName (partialName);\r
-                               }\r
-\r
-                               if (assembly == null)\r
-                                       throw new ApplicationException ("Assembly not found:" + assemblyName);\r
-\r
-                               return assembly;\r
-                       }\r
                }\r
                \r
 \r
                class TagNameFoundry : Foundry\r
                {\r
-                       string assemblyName;\r
                        string tagName;\r
-                       string nameSpace;\r
-                       string typeName;\r
                        Type type;\r
 \r
-                       public TagNameFoundry (string assemblyName, string tagName, string nameSpace, string typeName)\r
+                       public TagNameFoundry (string tagName, Type type)\r
                        {\r
-                               this.assemblyName = assemblyName;\r
                                this.tagName = tagName;\r
-                               this.nameSpace = nameSpace;\r
-                               this.typeName = typeName;\r
+                               this.type = type;\r
                        }\r
 \r
                        public override Type GetType (string componentName)\r
                        {\r
                                if (0 != String.Compare (componentName, tagName, true))\r
-                                       throw new ArgumentException (componentName + " != " + tagName);\r
+                                       return null;\r
                                \r
-                               if (type != null)\r
-                                       return type;\r
-                                       \r
-                               Assembly assembly = LoadAssembly (assemblyName);\r
-                               type =  assembly.GetType (nameSpace + "." + typeName, true, true);\r
                                return type;\r
                        }\r
 \r
@@ -146,30 +106,17 @@ namespace System.Web.Compilation
                class AssemblyFoundry : Foundry\r
                {\r
                        string nameSpace;\r
-                       string assemblyName;\r
                        Assembly assembly;\r
 \r
-                       public AssemblyFoundry (string assemblyName, string nameSpace)\r
+                       public AssemblyFoundry (Assembly assembly, string nameSpace)\r
                        {\r
-                               this.assemblyName = assemblyName;\r
+                               this.assembly = assembly;\r
                                this.nameSpace = nameSpace;\r
-                               assembly = null;\r
                        }\r
 \r
                        public override Type GetType (string componentName)\r
                        {\r
-                               Assembly ass = EnsureAssembly (componentName);\r
-\r
-                               return ass.GetType (nameSpace + "." + componentName, true, true);\r
-                       }\r
-                       \r
-                       Assembly EnsureAssembly (string componentName)\r
-                       {\r
-                               if (assembly != null)\r
-                                       return assembly;\r
-\r
-                               assembly = LoadAssembly (assemblyName);\r
-                               return assembly;\r
+                               return assembly.GetType (nameSpace + "." + componentName, true, true);\r
                        }\r
                }\r
 \r
diff --git a/mcs/class/System.Web/System.Web.Compilation/AspElements.cs b/mcs/class/System.Web/System.Web.Compilation/AspElements.cs
deleted file mode 100644 (file)
index 817cef8..0000000
+++ /dev/null
@@ -1,907 +0,0 @@
-//
-// System.Web.Compilation.AspElements
-//
-// Authors:
-//     Gonzalo Paniagua Javier (gonzalo@ximian.com)
-//
-// (C) 2002 Ximian, Inc (http://www.ximian.com)
-//
-using System;
-using System.Collections;
-using System.IO;
-using System.Reflection;
-using System.Text;
-using System.Web.UI;
-using System.Web.UI.HtmlControls;
-using System.Web.UI.WebControls;
-using System.Web.Util;
-
-namespace System.Web.Compilation
-{
-       
-       enum ElementType
-       {
-               TAG,
-               PLAINTEXT
-       }
-
-       abstract class Element
-       {
-               private ElementType elementType;
-
-               public Element (ElementType type)
-               {
-                       elementType = type;
-               }
-               
-               public ElementType GetElementType
-               {
-                       get { return elementType; }
-               }
-       } // class Element
-
-       class PlainText : Element
-       {
-               private StringBuilder text;
-
-               public PlainText () : base (ElementType.PLAINTEXT)
-               {
-                       text = new StringBuilder ();
-               }
-
-               public PlainText (StringBuilder text) : base (ElementType.PLAINTEXT)
-               {
-                       this.text = text;
-               }
-
-               public PlainText (string text) : this ()
-               {
-                       this.text.Append (text);
-               }
-
-               public void Append (string more)
-               {
-                       text.Append (more);
-               }
-               
-               public string Text
-               {
-                       get { return text.ToString (); }
-               }
-
-               public override string ToString ()
-               {
-                       return "PlainText: " + Text;
-               }
-       }
-
-       enum TagType
-       {
-               DIRECTIVE,
-               HTML,
-               HTMLCONTROL,
-               SERVERCONTROL,
-               INLINEVAR,
-               INLINECODE,
-               CLOSING,
-               SERVEROBJECT,
-               PROPERTYTAG,
-               CODERENDER,
-               DATABINDING,
-               SERVERCOMMENT,
-               NOTYET
-       }
-
-       /*
-        * Attributes and values are stored in a couple of ArrayList in Add ().
-        * When MakeHash () is called, they are converted to a Hashtable. If there are any
-        * attributes duplicated it throws an ArgumentException.
-        *
-        * The [] operator works with the Hashtable if the values are in it, otherwise
-        * it uses the ArrayList's.
-        *
-        * Why? You can have a tag in HTML like <a att="value" att="xxx">, but not in tags
-        * marked runat=server and Hashtable requires the key to be unique.
-        * 
-        */
-       class TagAttributes
-       {
-               private Hashtable atts_hash;
-               private ArrayList keys;
-               private ArrayList values;
-               private bool got_hashed;
-
-               public TagAttributes ()
-               {
-                       got_hashed = false;
-                       keys = new ArrayList ();
-                       values = new ArrayList ();
-               }
-
-               private void MakeHash ()
-               {
-                       atts_hash = new Hashtable (CaseInsensitiveHashCodeProvider.Default,
-                                                  CaseInsensitiveComparer.Default);
-                       for (int i = 0; i < keys.Count; i++)
-                               atts_hash.Add (keys [i], values [i]);
-                       got_hashed = true;
-                       keys = null;
-                       values = null;
-               }
-               
-               public bool IsRunAtServer ()
-               {
-                       return got_hashed;
-               }
-
-               public void Add (object key, object value)
-               {
-                       if (key != null && value != null &&
-                           0 == String.Compare ((string) key,  "runat", true) &&
-                           0 == String.Compare ((string) value,  "server", true))
-                               MakeHash ();
-
-                       if (got_hashed)
-                               atts_hash.Add (key, value);
-                       else {
-                               keys.Add (key);
-                               values.Add (value);
-                       }
-               }
-               
-               public ICollection Keys 
-               {
-                       get { return (got_hashed ? atts_hash.Keys : keys); }
-               }
-
-               private int CaseInsensitiveSearch (string key)
-               {
-                       // Hope not to have many attributes when the tag is not a server tag...
-                       for (int i = 0; i < keys.Count; i++){
-                               if (0 == String.Compare ((string) keys [i], key, true))
-                                       return i;
-                       }
-                       return -1;
-               }
-               
-               public object this [object key]
-               {
-                       get {
-                               if (got_hashed)
-                                       return atts_hash [key];
-
-                               int idx = CaseInsensitiveSearch ((string) key);
-                               if (idx == -1)
-                                       return null;
-                                               
-                               return values [idx];
-                       }
-
-                       set {
-                               if (got_hashed)
-                                       atts_hash [key] = value;
-                               else {
-                                       int idx = CaseInsensitiveSearch ((string) key);
-                                       keys [idx] = value;
-                               }
-                       }
-               }
-               
-               public int Count 
-               {
-                       get { return (got_hashed ? atts_hash.Count : keys.Count);}
-               }
-
-               public bool IsDataBound (string att)
-               {
-                       if (att == null || !got_hashed)
-                               return false;
-
-                       return (att.StartsWith ("<%#") && att.EndsWith ("%>"));
-               }
-               
-               public override string ToString ()
-               {
-                       StringBuilder result = new StringBuilder ();
-                       string value;
-                       foreach (string key in Keys){
-                               result.Append (key);
-                               value = this [key] as string;
-                               if (value != null)
-                                       result.AppendFormat ("=\"{0}\"", value);
-
-                               result.Append (' ');
-                       }
-
-                       if (result.Length > 0 && result [result.Length - 1] == ' ')
-                               result.Length--;
-                               
-                       return result.ToString ();
-               }
-       }
-
-       class Tag : Element
-       {
-               protected string tag;
-               protected TagType tagType;
-               protected TagAttributes attributes;
-               protected bool self_closing;
-               protected bool hasDefaultID;
-               private static int ctrlNumber = 1;
-               ArrayList elements;
-
-               internal Tag (ElementType etype) : base (etype) { }
-
-               internal Tag (Tag other) :
-                       this (other.tag, other.attributes, other.self_closing)
-               {
-                       this.tagType = other.tagType;
-               }
-
-               public Tag (string tag, TagAttributes attributes, bool self_closing) :
-                         base (ElementType.TAG)
-               {
-                       if (tag == null)
-                               throw new ArgumentNullException ();
-
-                       this.tag = tag;
-                       this.attributes = attributes;
-                       this.tagType = TagType.NOTYET;
-                       this.self_closing = self_closing;
-                       this.hasDefaultID = false;
-               }
-
-               void ParseError (string msg, int line, int col)
-               {
-                       string exc = String.Format ("error parsing attributes: {0}", msg);
-                       throw new HttpException (exc);
-               }
-
-               void TagParsed (Tag tag, int line, int col)
-               {
-                       elements.Add (tag);
-               }
-
-               void TextParsed (string msg, int line, int col)
-               {
-                       elements.Add (new PlainText (msg));
-               }
-
-               public ArrayList GetElements ()
-               {
-                       string text = this.PlainHtml;
-                       string inner = text.Substring (1, text.Length - 2);
-                       byte [] bytes = WebEncoding.Encoding.GetBytes (inner);
-                       AspTokenizer tok = new AspTokenizer ("@@inner_string", new MemoryStream (bytes));
-                       AspParser parser = new AspParser (tok);
-
-                       elements = new ArrayList ();
-                       parser.Error += new ParseErrorHandler (ParseError);
-                       parser.TagParsed += new TagParsedHandler (TagParsed);
-                       parser.TextParsed += new TextParsedHandler (TextParsed);
-
-                       parser.Parse ();
-
-                       elements.Insert (0, new PlainText ("<"));
-                       elements.Add (new PlainText (">"));
-
-                       return elements;
-               }
-               public string TagID
-               {
-                       get { return tag; }
-               }
-
-               public TagType TagType
-               {
-                       get { return tagType; }
-               }
-
-               public bool SelfClosing
-               {
-                       get { return self_closing; }
-               }
-
-               public TagAttributes Attributes
-               {
-                       get { return attributes; }
-               }
-
-               public string PlainHtml
-               {
-                       get {
-                               StringBuilder plain = new StringBuilder ();
-                               plain.Append ('<');
-                               if (tagType == TagType.CLOSING)
-                                       plain.Append ('/');
-                               plain.Append (tag);
-                               if (attributes != null){
-                                       plain.Append (' ');
-                                       plain.Append (attributes.ToString ());
-                               }
-                               
-                               if (self_closing)
-                                       plain.Append ('/');
-
-                               plain.Append ('>');
-                               return plain.ToString ();
-                       }
-               }
-
-               public override string ToString ()
-               {
-                       return TagID + " " + Attributes + " " + self_closing;
-               }
-
-               public bool HasDefaultID
-               {
-                       get { return hasDefaultID; }
-               }
-               
-               protected virtual void SetNewID ()
-               {
-                       if (attributes == null)
-                               attributes = new TagAttributes ();
-                       attributes.Add ("ID", GetDefaultID ());
-                       hasDefaultID = true;
-               }
-
-               public static string GetDefaultID ()
-               {
-                       return "_control" + ctrlNumber++;
-               }
-       }
-
-       class CloseTag : Tag
-       {
-               public CloseTag (string tag) : base (tag, null, false)
-               {
-                       tagType = TagType.CLOSING;
-               }
-       }
-
-       class Directive : Tag
-       {
-               // 'codebehind' is just ignored for Page, Application and Control
-               private static Hashtable directivesHash;
-               private static string [] page_atts = {  "AspCompat", "AutoEventWireup", "Buffer",
-                                                       "ClassName", "ClientTarget", "CodePage",
-                                                       "CompilerOptions", "ContentType", "Culture", "Debug",
-                                                       "Description", "EnableSessionState", "EnableViewState",
-                                                       "EnableViewStateMac", "ErrorPage", "Explicit",
-                                                       "Inherits", "Language", "LCID", "ResponseEncoding",
-                                                       "Src", "SmartNavigation", "Strict", "Trace",
-                                                       "TraceMode", "Transaction", "UICulture",
-                                                       "WarningLevel", "CodeBehind" };
-
-               private static string [] control_atts = { "AutoEventWireup", "ClassName", "CompilerOptions",
-                                                         "Debug", "Description", "EnableViewState",
-                                                         "Explicit", "Inherits", "Language", "Strict", "Src",
-                                                         "WarningLevel", "CodeBehind", "TargetSchema" };
-
-               private static string [] import_atts = { "namespace" };
-               private static string [] implements_atts = { "interface" };
-               private static string [] assembly_atts = { "name", "src" };
-               private static string [] register_atts = { "tagprefix", "tagname", "Namespace",
-                                                          "Src", "Assembly" };
-
-               private static string [] outputcache_atts = { "Duration", "Location", "VaryByControl", 
-                                                             "VaryByCustom", "VaryByHeader", "VaryByParam" };
-               private static string [] reference_atts = { "page", "control" };
-
-               private static string [] webservice_atts = { "class", "codebehind", "debug", "language" };
-
-               private static string [] application_atts = { "description", "inherits", "codebehind" };
-
-               static Directive ()
-               {
-                       InitHash ();
-               }
-               
-               private static void InitHash ()
-               {
-                       CaseInsensitiveHashCodeProvider provider = new CaseInsensitiveHashCodeProvider ();
-                       CaseInsensitiveComparer comparer =  new CaseInsensitiveComparer ();
-
-                       directivesHash = new Hashtable (provider, comparer); 
-
-                       // Use Hashtable 'cause is O(1) in Contains (ArrayList is O(n))
-                       Hashtable valid_attributes = new Hashtable (provider, comparer);
-                       foreach (string att in page_atts) valid_attributes.Add (att, null);
-                       directivesHash.Add ("PAGE", valid_attributes);
-
-                       valid_attributes = new Hashtable (provider, comparer);
-                       foreach (string att in control_atts) valid_attributes.Add (att, null);
-                       directivesHash.Add ("CONTROL", valid_attributes);
-
-                       valid_attributes = new Hashtable (provider, comparer);
-                       foreach (string att in import_atts) valid_attributes.Add (att, null);
-                       directivesHash.Add ("IMPORT", valid_attributes);
-
-                       valid_attributes = new Hashtable (provider, comparer);
-                       foreach (string att in implements_atts) valid_attributes.Add (att, null);
-                       directivesHash.Add ("IMPLEMENTS", valid_attributes);
-
-                       valid_attributes = new Hashtable (provider, comparer);
-                       foreach (string att in register_atts) valid_attributes.Add (att, null);
-                       directivesHash.Add ("REGISTER", valid_attributes);
-
-                       valid_attributes = new Hashtable (provider, comparer);
-                       foreach (string att in assembly_atts) valid_attributes.Add (att, null);
-                       directivesHash.Add ("ASSEMBLY", valid_attributes);
-
-                       valid_attributes = new Hashtable (provider, comparer);
-                       foreach (string att in outputcache_atts) valid_attributes.Add (att, null);
-                       directivesHash.Add ("OUTPUTCACHE", valid_attributes);
-
-                       valid_attributes = new Hashtable (provider, comparer);
-                       foreach (string att in reference_atts) valid_attributes.Add (att, null);
-                       directivesHash.Add ("REFERENCE", valid_attributes);
-
-                       valid_attributes = new Hashtable (provider, comparer);
-                       foreach (string att in webservice_atts) valid_attributes.Add (att, null);
-                       directivesHash.Add ("WEBSERVICE", valid_attributes);
-
-                       valid_attributes = new Hashtable (provider, comparer);
-                       foreach (string att in application_atts) valid_attributes.Add (att, null);
-                       directivesHash.Add ("APPLICATION", valid_attributes);
-               }
-               
-               public Directive (string tag, TagAttributes attributes) :
-                      base (tag, attributes, true)
-               {
-                       CheckAttributes ();
-                       tagType = TagType.DIRECTIVE;
-               }
-
-               private void CheckAttributes ()
-               {
-                       Hashtable atts;
-                       if (!(directivesHash [tag] is Hashtable))
-                               throw new ApplicationException ("Unknown directive: " + tag);
-
-                       if (attributes == null || attributes.Count == 0)
-                               return;
-
-                       atts = (Hashtable) directivesHash [tag];
-                       foreach (string att in attributes.Keys){
-                               if (!atts.Contains (att))
-                                       throw new ApplicationException ("Attribute " + att +
-                                                                       " not valid for tag " + tag);
-                       }
-               }
-
-               public static bool IsDirectiveID (string id)
-               {
-                       return directivesHash.Contains (id);
-               }
-               
-               public override string ToString ()
-               {
-                       return "Directive: " + tag;
-               }
-       }
-
-       class ServerObjectTag : Tag
-       {
-               public ServerObjectTag (Tag tag) :
-                       base (tag.TagID, tag.Attributes, tag.SelfClosing) 
-               {
-                       tagType = TagType.SERVEROBJECT;
-                       if (!attributes.IsRunAtServer ())
-                               throw new ApplicationException ("<object> without runat=server");
-                       
-                       if (attributes.Count != 3 || !SelfClosing || ObjectID == null || ObjectClass == null)
-                               throw new ApplicationException ("Incorrect syntax: <object id=\"name\" " + 
-                                                               "class=\"full.class.name\" runat=\"server\" />");
-               }
-
-               public string ObjectID
-               {
-                       get { return (string) attributes ["id"]; }
-               }
-                       
-               public string ObjectClass
-               {
-                       get { return (string) attributes ["class"]; }
-               }
-       }
-
-       class HtmlControlTag : Tag
-       {
-               private Type control_type;
-               private bool is_container;
-               private string parse_children;
-               private bool got_parse_children;
-
-               private static Hashtable controls;
-               private static Hashtable inputTypes;
-
-               private static void InitHash ()
-               {
-                       controls = new Hashtable (new CaseInsensitiveHashCodeProvider (),
-                                                 new CaseInsensitiveComparer ()); 
-
-                       controls.Add ("A", typeof (HtmlAnchor));
-                       controls.Add ("BUTTON", typeof (HtmlButton));
-                       controls.Add ("FORM", typeof (HtmlForm));
-                       controls.Add ("IMG", typeof (HtmlImage));
-                       controls.Add ("INPUT", "INPUT");
-                       controls.Add ("SELECT", typeof (HtmlSelect));
-                       controls.Add ("TABLE", typeof (HtmlTable));
-                       controls.Add ("TD", typeof (HtmlTableCell));
-                       controls.Add ("TH", typeof (HtmlTableCell));
-                       controls.Add ("TR", typeof (HtmlTableRow));
-                       controls.Add ("TEXTAREA", typeof (HtmlTextArea));
-
-                       inputTypes = new Hashtable (new CaseInsensitiveHashCodeProvider (),
-                                                   new CaseInsensitiveComparer ());
-
-                       inputTypes.Add ("BUTTON", typeof (HtmlInputButton));
-                       inputTypes.Add ("SUBMIT", typeof (HtmlInputButton));
-                       inputTypes.Add ("RESET", typeof (HtmlInputButton));
-                       inputTypes.Add ("CHECKBOX", typeof (HtmlInputCheckBox));
-                       inputTypes.Add ("FILE", typeof (HtmlInputFile));
-                       inputTypes.Add ("HIDDEN", typeof (HtmlInputHidden));
-                       inputTypes.Add ("IMAGE", typeof (HtmlInputImage));
-                       inputTypes.Add ("RADIO", typeof (HtmlInputRadioButton));
-                       inputTypes.Add ("TEXT", typeof (HtmlInputText));
-                       inputTypes.Add ("PASSWORD", typeof (HtmlInputText));
-               }
-               
-               static HtmlControlTag ()
-               {
-                       InitHash ();
-               }
-               
-               public HtmlControlTag (string tag, TagAttributes attributes, bool self_closing) : 
-                       base (tag, attributes, self_closing) 
-               {
-                       SetData ();
-                       if (attributes == null || attributes ["ID"] == null)
-                               SetNewID ();
-               }
-
-               public HtmlControlTag (Tag source_tag) :
-                       this (source_tag.TagID, source_tag.Attributes, source_tag.SelfClosing) 
-               {
-               }
-
-               private void SetData ()
-               {
-                       tagType = TagType.HTMLCONTROL; 
-                       if (!(controls [tag] is string)){
-                               control_type = (Type) controls [tag];
-                               if (control_type == null)
-                                       control_type = typeof (HtmlGenericControl);
-                               is_container = (0 != String.Compare (tag, "img", true));
-                       } else {
-                               string type_value = (string) attributes ["TYPE"];
-                               if (type_value== null)
-                                       throw new ArgumentException ("INPUT tag without TYPE attribute!!!");
-
-                               control_type = (Type) inputTypes [type_value];
-                               //TODO: what does MS with this one?
-                               if (control_type == null)
-                                       throw new ArgumentException ("Unknown input type -> " + type_value);
-                               is_container = false;
-                               self_closing = true; // All <input ...> are self-closing
-                       }
-               }
-
-               public Type ControlType
-               {
-                       get { return control_type; }
-               }
-
-               public string ControlID
-               {
-                       get { return (string) attributes ["ID"]; }
-               }
-
-               public bool IsContainer
-               {
-                       get { return is_container; }
-               }
-
-               public string ParseChildren {
-                       get {
-                               if (got_parse_children)
-                                       return parse_children;
-
-                               got_parse_children = true;
-                               object [] custom_atts = control_type.GetCustomAttributes (true);
-                               foreach (object att in custom_atts) {
-                                       if (!(att is ParseChildrenAttribute))
-                                               continue;
-
-                                       ParseChildrenAttribute pc = (ParseChildrenAttribute) att;
-                                       if (pc.ChildrenAsProperties == true)
-                                               parse_children = pc.DefaultProperty;
-
-                                       return parse_children;
-                               }
-
-                               return parse_children;
-                       }
-               }
-               
-               public override string ToString ()
-               {
-                       string ret = "HtmlControlTag: " + tag + " Name: " + ControlID + "Type:" +
-                                    control_type.ToString () + "\n\tAttributes:\n";
-
-                       foreach (string key in attributes.Keys){
-                               ret += "\t" + key + "=" + attributes [key];
-                       }
-                       return ret;
-               }
-       }
-
-       enum ChildrenKind
-       {
-               NONE,
-               /* 
-                * Children must be ASP.NET server controls. Literal text is passed as LiteralControl.
-                * Child controls and text are added using AddParsedSubObject ().
-                */
-               CONTROLS, 
-               /*
-                * Children must correspond to properties of the parent control. No literal text allowed.
-                */
-               PROPERTIES,
-               /*
-                * Special case used inside <columns>...</columns>
-                * Only allow DataGridColumn and derived classes.
-                */
-               DBCOLUMNS,
-               /*
-                * Special case for list controls (ListBox, DropDownList...)
-                */
-               LISTITEM,
-               /* For HtmlSelect children. They are <option> tags that must
-                * be treated as ListItem
-                */
-               OPTION,
-               /* Childs of HtmlTable */
-               HTMLROW,
-               /* Childs of HtmlTableRow */
-               HTMLCELL
-       }
-
-       // TODO: support for ControlBuilderAttribute that may be used in custom controls
-       class AspComponent : Tag
-       {
-               private Type type;
-               private string alias;
-               private string control_type;
-               private bool is_close_tag;
-               private bool allow_children;
-               private ChildrenKind children_kind;
-               private string defaultPropertyName;
-               private Type defaultPropertyType;
-
-               ChildrenKind ChildrenKindFromProperty (Type type, string propertyName)
-               {
-                       PropertyInfo prop = type.GetProperty (propertyName);
-                       if (prop == null)
-                               return ChildrenKind.LISTITEM;
-
-                       defaultPropertyType = prop.PropertyType;
-                       if (typeof (TableRowCollection).IsAssignableFrom (defaultPropertyType))
-                               return ChildrenKind.HTMLROW;
-
-                       if (typeof (TableCellCollection).IsAssignableFrom (defaultPropertyType))
-                               return ChildrenKind.HTMLCELL;
-
-                       return ChildrenKind.LISTITEM;
-               }
-
-               private ChildrenKind GuessChildrenKind (Type type)
-               {
-                       object [] custom_atts = type.GetCustomAttributes (true);
-                       foreach (object custom_att in custom_atts){
-                               if (custom_att is ParseChildrenAttribute){
-                                       /* FIXME
-                                        * When adding full support for custom controls, we gotta
-                                        * bear in mind the pca.DefaultProperty value
-                                        */
-                                       ParseChildrenAttribute pca = custom_att as ParseChildrenAttribute;
-                                       defaultPropertyName = pca.DefaultProperty;
-                                       /* this property will be true for all controls derived from
-                                        * WebControls. */
-                                       if (pca.ChildrenAsProperties == false)
-                                               return ChildrenKind.CONTROLS;
-                                       else if (defaultPropertyName == "")
-                                               return ChildrenKind.PROPERTIES;
-                                       else
-                                               return ChildrenKindFromProperty (type, defaultPropertyName);
-                               }
-                       }
-
-                       return ChildrenKind.NONE;
-               }
-
-               private static bool GuessAllowChildren (Type type)
-               {
-                       PropertyInfo controls = type.GetProperty ("Controls");
-                       if (controls == null)
-                               return false;
-                       MethodInfo getm = controls.GetGetMethod ();
-                       object control_instance = Activator.CreateInstance (type);
-                       object control_collection = getm.Invoke (control_instance, null);
-                       return (!(control_collection is System.Web.UI.EmptyControlCollection));
-               }
-               
-               public AspComponent (Tag input_tag, Type type) :
-                       base (input_tag)
-               {
-                       tagType = TagType.SERVERCONTROL;
-                       this.is_close_tag = input_tag is CloseTag;
-                       this.type = type;
-                       this.defaultPropertyName = "";
-                       this.allow_children = GuessAllowChildren (type);
-                       if (input_tag.SelfClosing)
-                               this.children_kind = ChildrenKind.NONE;
-                       else if (type == typeof (System.Web.UI.WebControls.DataGridColumn) ||
-                                type.IsSubclassOf (typeof (System.Web.UI.WebControls.DataGridColumn)))
-                               this.children_kind = ChildrenKind.PROPERTIES;
-                       else if (type == typeof (System.Web.UI.WebControls.ListItem))
-                               this.children_kind = ChildrenKind.CONTROLS;
-                       else
-                               this.children_kind = GuessChildrenKind (type);
-
-                       int pos = input_tag.TagID.IndexOf (':');
-                       alias = tag.Substring (0, pos);
-                       control_type = tag.Substring (pos + 1);
-                       if (attributes == null || attributes ["ID"] == null)
-                               SetNewID ();
-               }
-
-               public Type ComponentType
-               {
-                       get { return type; }
-               }
-               
-               public string ControlID
-               {
-                       get { return (string) attributes ["ID"]; }
-               }
-
-               public bool IsCloseTag
-               {
-                       get { return is_close_tag; }
-               }
-
-               public bool AllowChildren
-               {
-                       get { return allow_children; }
-               }
-
-               public ChildrenKind ChildrenKind
-               {
-                       get { return children_kind; }   
-               }
-
-               public string DefaultPropertyName
-               {
-                       get { return defaultPropertyName; }     
-               }
-               
-               public Type DefaultPropertyType
-               {
-                       get { return defaultPropertyType; }     
-               }
-                       
-               public override string ToString ()
-               {
-                       return type.ToString () + " Alias: " + alias + " ID: " + (string) attributes ["id"];
-               }
-       }
-
-       class PropertyTag : Tag
-       {
-               private Type type;
-               private string name;
-
-               public PropertyTag (Tag tag, Type type, string name)
-                       : base (tag)
-               {
-                       tagType = TagType.PROPERTYTAG;
-                       SetNewID ();
-                       this.name = name;
-                       this.type = type;
-               }
-
-               public Type PropertyType
-               {
-                       get { return type; }
-               }
-
-               public string PropertyID
-               {
-                       get { return (string) attributes ["ID"]; }
-               }
-
-               public string PropertyName
-               {
-                       get { return name; }
-               }
-       }
-
-       class CodeRenderTag : Tag
-       {
-               private string code;
-               private bool isVarName;
-
-               public CodeRenderTag (bool isVarName, string code) : base ("", null, false)
-               {
-                       tagType = TagType.CODERENDER;
-                       this.isVarName = isVarName;
-                       this.code = code.Trim ();
-               }
-
-               public string Code
-               {
-                       get { return code; }
-               }
-
-               public bool IsVarName
-               {
-                       get { return isVarName; }
-               }
-
-               public string AsText
-               {
-                       get { return "<%" + (IsVarName ? "=" : "") + Code + "%>"; }
-               }       
-       }
-
-       class DataBindingTag : Tag
-       {
-               private string data;
-
-               public DataBindingTag (string data) : base ("", null, false)
-               {
-                       tagType = TagType.DATABINDING;
-                       this.data = data.Trim ();
-               }
-
-               public string Data
-               {
-                       get { return data; }
-               }
-
-               public string AsText
-               {
-                       get { return "<%#" + Data + "%>"; }
-               }       
-       }
-       
-       class ServerComment : Tag
-       {
-               public ServerComment (string tag)
-                       : base (ElementType.TAG)
-               {
-                       if (tag == null)
-                               throw new ArgumentNullException ();
-
-                       this.tag = tag;
-                       this.attributes = null;
-                       this.tagType = TagType.SERVERCOMMENT;
-                       this.self_closing = true;
-                       this.hasDefaultID = false;
-               }
-               
-               public override string ToString ()
-               {
-                       return TagID;
-               }
-
-               protected override void SetNewID ()
-               {
-                       throw new NotSupportedException ();
-               }
-       }
-}
-
index b92bd1b62d3628dad78b0fbccf133fe232a1177a..df8970c5d0085128fd44fc27b89eeb7fec68e107 100644 (file)
 //
 using System;
 using System.Collections;
-using System.ComponentModel;
-using System.Drawing;
-using System.Diagnostics;
 using System.IO;
-using System.Reflection;
 using System.Text;
-using System.Text.RegularExpressions;
 using System.Web.UI;
-using System.Web.UI.HtmlControls;
-using System.Web.UI.WebControls;
-using System.Web.Util;
 
 namespace System.Web.Compilation
 {
-
-class ControlStack
-{
-       private Stack controls;
-       private ControlStackData top;
-       private bool space_between_tags;
-       private bool sbt_valid;
-
-       class ControlStackData 
+       class BuilderLocation
        {
-               public Type controlType;
-               public string controlID;
-               public string tagID;
-               public ChildrenKind childKind;
-               public string defaultPropertyName;
-               public int childrenNumber;
-               public Type container;
-               public StringBuilder dataBindFunction;
-               public StringBuilder codeRenderFunction;
-               public bool useCodeRender;
-               public int codeRenderIndex;
-
-               public ControlStackData (Type controlType,
-                                        string controlID,
-                                        string tagID,
-                                        ChildrenKind childKind,
-                                        string defaultPropertyName,
-                                        Type container)
-               {
-                       this.controlType = controlType;
-                       this.controlID = controlID;
-                       this.tagID = tagID;
-                       this.childKind = childKind;
-                       this.defaultPropertyName = defaultPropertyName;
-                       this.container = container;
-                       childrenNumber = 0;
-               }
+               public ControlBuilder Builder;
+               public ILocation Location;
 
-               public override string ToString ()
+               public BuilderLocation (ControlBuilder builder, ILocation location)
                {
-                       return controlType + " " + controlID + " " + tagID + " " + childKind + " " + childrenNumber;
+                       this.Builder = builder;
+                       this.Location = location;
                }
        }
        
-       public ControlStack ()
+       class BuilderLocationStack : Stack
        {
-               controls = new Stack ();
-       }
+               public override void Push (object o)
+               {
+                       if (!(o is BuilderLocation))
+                               throw new InvalidOperationException ();
 
-       private Type GetContainerType (Type type)
-       {
-               if (type != typeof (System.Web.UI.Control) &&
-                   !type.IsSubclassOf (typeof (System.Web.UI.Control)))
-                       return null;
+                       base.Push (o);
+               }
                
-               Type container_type;
-               if (type == typeof (System.Web.UI.WebControls.DataList))
-                       container_type = typeof (System.Web.UI.WebControls.DataListItem);
-               else if (type == typeof (System.Web.UI.WebControls.DataGrid))
-                       container_type = typeof (System.Web.UI.WebControls.DataGridItem);
-               else if (type == typeof (System.Web.UI.WebControls.Repeater))
-                       container_type = typeof (System.Web.UI.WebControls.RepeaterItem);
-               else if (type == typeof (ListControl) || type.IsSubclassOf (typeof (ListControl)))
-                       container_type = type;
-               else
-                       container_type = Container;
-
-               return container_type;
-       }
-
-       public void Push (object o)
-       {
-               if (!(o is ControlStackData))
-                       return;
-
-               controls.Push (o);
-               top = (ControlStackData) o;
-               sbt_valid = false;
-       }
-       
-       public void Push (Type controlType,
-                         string controlID,
-                         string tagID,
-                         ChildrenKind childKind,
-                         string defaultPropertyName)
-       {
-               Type container_type = null;
-               if (controlType != null){
-                       AddChild ();
-                       container_type = GetContainerType (controlType);
-                       if (container_type == null)
-                               container_type = this.Container;
+               public virtual void Push (ControlBuilder builder, ILocation location)
+               {
+                       BuilderLocation bl = new BuilderLocation (builder, location);
+                       Push (bl);
                }
 
-               top = new ControlStackData (controlType,
-                                           controlID,
-                                           tagID,
-                                           childKind,
-                                           defaultPropertyName,
-                                           container_type);
-               sbt_valid = false;
-               controls.Push (top);
-       }
-
-       public object Pop ()
-       {
-               object item = controls.Pop ();
-               if (controls.Count != 0)
-                       top = (ControlStackData) controls.Peek ();
-               sbt_valid = false;
-               return item;
-       }
-
-       public Type PeekType ()
-       {
-               return top.controlType;
-       }
-
-       public string PeekControlID ()
-       {
-               return top.controlID;
-       }
-
-       public string PeekTagID ()
-       {
-               return top.tagID;
-       }
-
-       public ChildrenKind PeekChildKind ()
-       {
-               return top.childKind;
-       }
-
-       public string PeekDefaultPropertyName ()
-       {
-               return top.defaultPropertyName;
-       }
-
-       public void AddChild ()
-       {
-               if (top != null)
-                       top.childrenNumber++;
-       }
-
-       public bool HasDataBindFunction ()
-       {
-               if (top.dataBindFunction == null || top.dataBindFunction.Length == 0)
-                       return false;
-               return true;
-       }
-       
-       public bool UseCodeRender
-       {
-               get {
-                       if (top.codeRenderFunction == null || top.codeRenderFunction.Length == 0)
-                               return false;
-                       return top.useCodeRender;
+               public new BuilderLocation Peek ()
+               {
+                       return (BuilderLocation) base.Peek ();
                }
 
-               set { top.useCodeRender= value; }
-       }
-       
-       public bool SpaceBetweenTags
-       {
-               get {
-                       if (!sbt_valid){
-                               sbt_valid = true;
-                               Type type = top.controlType;
-                               if (type.Namespace == "System.Web.UI.WebControls")
-                                       space_between_tags = true;
-                               else if (type.IsSubclassOf (typeof (System.Web.UI.WebControls.WebControl)))
-                                       space_between_tags = true;
-                               else if (type == typeof (System.Web.UI.HtmlControls.HtmlSelect))
-                                       space_between_tags = true;
-                               else if (type == typeof (System.Web.UI.HtmlControls.HtmlTable))
-                                       space_between_tags = true;
-                               else if (type == typeof (System.Web.UI.HtmlControls.HtmlTableRow))
-                                       space_between_tags = true;
-                               else if (type == typeof (System.Web.UI.HtmlControls.HtmlTableCell))
-                                       space_between_tags = true;
-                               else
-                                       space_between_tags = false;
-                       }
-                       return space_between_tags;
-               }
-       }
-       
-       public Type Container {
-               get {
-                       if (top == null)
-                               return null;
-                               
-                       return top.container;
-               }
-       }
-       
-       public StringBuilder DataBindFunction
-       {
-               get {
-                       if (top.dataBindFunction == null)
-                               top.dataBindFunction = new StringBuilder ();
-                       return top.dataBindFunction;
+               public new BuilderLocation Pop ()
+               {
+                       return (BuilderLocation) base.Pop ();
                }
-       }
 
-       public int CodeRenderIndex {
-               get {
-                       return top.codeRenderIndex++;
-               }
-       }
-       
-       public StringBuilder CodeRenderFunction
-       {
-               get {
-                       if (top.codeRenderFunction == null)
-                               top.codeRenderFunction = new StringBuilder ();
-                       return top.codeRenderFunction;
+               public ControlBuilder Builder {
+                       get { return Peek ().Builder; }
                }
        }
 
-       public int ChildIndex
-       {
-               get { return top.childrenNumber - 1; }
-       }
-       
-       public int Count
-       {
-               get { return controls.Count; }
-       }
-
-       public override string ToString ()
+       class AspGenerator
        {
-               return top.ToString () + " " + top.useCodeRender;
-       }
-               
-}
-
-enum ScriptStatus
-{
-       Close,
-       Open,
-       Text
-}
-
-class AspGenerator
-{
-       object [] parts;
-       StringBuilder prolog;
-       StringBuilder declarations;
-       StringBuilder script;
-       StringBuilder constructor;
-       StringBuilder init_funcs;
-       StringBuilder epilog;
-       StringBuilder current_function;
-       StringBuilder textChunk;
-       Stack functions;
-       ControlStack controls;
-       bool parse_ok;
-       bool has_form_tag;
-       AspComponentFoundry aspFoundry;
-
-       string classDecl;
-       string className;
-       string interfaces;
-       string basetype;
-       string parent;
-       Type parentType;
-       string fullPath;
+               string filename;
+               AspParser parser;
+               BuilderLocationStack stack;
+               TemplateParser tparser;
+               StringBuilder text;
+               RootBuilder rootBuilder;
+               bool inScript;
+               ILocation location;
+               static Hashtable emptyHash = new Hashtable ();
 
-       Hashtable options;
-       string privateBinPath;
-       string main_directive;
-       static string app_file_wrong = "The content in the application file is not valid.";
-
-       bool isPage;
-       bool isUserControl;
-       bool isApplication;
-
-       Element current;
-       ScriptStatus sstatus = ScriptStatus.Close;
-       string waitClosing;
-       ArrayList dependencies;
-
-       HttpContext context;
-
-       SessionState sessionState = SessionState.Enabled;
-
-       static Type styleType = typeof (System.Web.UI.WebControls.Style);
-       static Type fontinfoType = typeof (System.Web.UI.WebControls.FontInfo);
+               public AspGenerator (TemplateParser tparser)
+               {
+                       this.tparser = tparser;
+                       this.filename = Path.GetFullPath (tparser.InputFile);
+                       tparser.AddDependency (tparser.InputFile);
+                       text = new StringBuilder ();
+                       stack = new BuilderLocationStack ();
+                       rootBuilder = new RootBuilder (tparser);
+                       stack.Push (rootBuilder, null);
+                       tparser.RootBuilder = rootBuilder;
+               }
 
-       enum UserControlResult
-       {
-               OK = 0,
-               FileNotFound = 1,
-               CompilationFailed = 2
-       }
+               BaseCompiler GetCompilerFromType ()
+               {
+                       Type type = tparser.GetType ();
+                       if (type == typeof (PageParser))
+                               return new PageCompiler ((PageParser) tparser);
 
-       enum SessionState
-       {
-               Enabled,
-               ReadOnly,
-               Disabled
-       }
-       
-       public AspGenerator (string pathToFile)
-       {
-               if (pathToFile == null)
-                       throw new ArgumentNullException ("pathToFile");
+                       if (type == typeof (ApplicationFileParser))
+                               return new GlobalAsaxCompiler ((ApplicationFileParser) tparser);
 
-               string filename = Path.GetFileName (pathToFile);
-               this.className = filename.Replace ('.', '_'); // Overridden by @ Page classname
-               this.className = className.Replace ('-', '_'); 
-               this.className = className.Replace (' ', '_');
-               Options ["ClassName"] = this.className;
-               this.fullPath = Path.GetFullPath (pathToFile);
+                       if (type == typeof (UserControlParser))
+                               return new UserControlCompiler ((UserControlParser) tparser);
 
-               this.has_form_tag = false;
-               AppDomainSetup setup = AppDomain.CurrentDomain.SetupInformation;
-               privateBinPath = setup.PrivateBinPath;
-               // This is a hack until we can run stuff in different domains
-               if (privateBinPath == null || privateBinPath.Length == 0)
-                       privateBinPath = "bin";
-                       
-               if (!Path.IsPathRooted (privateBinPath)) {
-                       string appbase = setup.ApplicationBase;
-                       if (appbase.StartsWith ("file://")) {
-                               appbase = appbase.Substring (7);
-                               if (Path.DirectorySeparatorChar != '/')
-                                       appbase = appbase.Replace ('/', Path.DirectorySeparatorChar);
-                       }
-                       privateBinPath = Path.Combine (appbase, privateBinPath);
+                       throw new Exception ("Got type: " + type);
                }
                
-               Init ();
-       }
-
-       public string BaseType {
-               get { return basetype; }
-
-               set {
-                       if (parent == null)
-                               parent = value;
-
-                       basetype = value;
-                       isUserControl = (basetype == "System.Web.UI.UserControl");
-                       isPage = (basetype == "System.Web.UI.Page");
-                       isApplication = (basetype == "System.Web.HttpApplication");
-               }
-       }
-
-       public bool IsUserControl {
-               get { return isUserControl; }
-       }
-       
-       public bool IsPage {
-               get { return isPage; }
-       }
-       
-       public bool IsApplication {
-               get { return isApplication; }
-       }
-
-       public string Interfaces {
-               get { return interfaces; }
-       }
+               public Type GetCompiledType ()
+               {
+                       //FIXME: use the encoding of the file or the one specified in the machine.config/web.config file.
+                       StreamReader reader = new StreamReader (filename, Encoding.Default);
+                       parser = new AspParser (filename, reader);
+                       parser.Error += new ParseErrorHandler (ParseError);
+                       parser.TagParsed += new TagParsedHandler (TagParsed);
+                       parser.TextParsed += new TextParsedHandler (TextParsed);
 
-       public Hashtable Options {
-               get {
-                       if (options == null)
-                               options = new Hashtable ();
+                       parser.Parse ();
+                       if (text.Length > 0)
+                               FlushText ();
 
-                       return options;
-               }
-       }
-       
-       public ArrayList Dependencies {
-               get { return dependencies; }
-       }
-       
-       internal HttpContext Context {
-               get { return context; }
-               set { context = value; }
-       }
-       
-       bool AddUsing (string nspace)
-       {
-               string _using = "using " + nspace + ";";
-               if (prolog.ToString ().IndexOf (_using) == -1) {
-                       prolog.AppendFormat ("\t{0}\n", _using);
-                       return true;
-               }
+                       if (stack.Count > 1)
+                               throw new ParseException (stack.Builder.location,
+                                               "Expecting </" + stack.Builder.TagName + ">" + stack.Builder);
 
-               return false;
-       }
+                       BaseCompiler compiler = GetCompilerFromType ();
 
-       void AddInterface (Type type)
-       {
-               AddInterface (type.ToString ());
-       }
-       
-       public void AddInterface (string iface)
-       {
-               if (interfaces == null) {
-                       interfaces = ", " + iface;
-               } else {
-                       string s = ", " + iface;
-                       if (interfaces.IndexOf (s) == -1)
-                               interfaces += s;
+                       /*
+                       IndentedTextWriter tw = new IndentedTextWriter (Console.Out, "    ");
+                       generator.GenerateCodeFromCompileUnit (unit, tw, new CodeGeneratorOptions());
+                       tw.Close ();
+                       */
+                       return compiler.GetCompiledType ();
                }
-       }
 
-       private AspComponentFoundry Foundry
-       {
-               get {
-                       if (aspFoundry == null)
-                               aspFoundry = new AspComponentFoundry ();
-
-                       return aspFoundry;
+               static void PrintLocation (ILocation loc)
+               {
+                       Console.WriteLine ("\tFile name: " + loc.Filename);
+                       Console.WriteLine ("\tBegin line: " + loc.BeginLine);
+                       Console.WriteLine ("\tEnd line: " + loc.EndLine);
+                       Console.WriteLine ("\tBegin column: " + loc.BeginColumn);
+                       Console.WriteLine ("\tEnd column: " + loc.EndColumn);
+                       Console.WriteLine ("\tPlainText: " + loc.PlainText);
+                       Console.WriteLine ();
                }
-       }
-
-       private void Init ()
-       {
-               dependencies = new ArrayList ();
-               dependencies.Add (fullPath);
-
-               controls = new ControlStack ();
-               controls.Push (typeof (System.Web.UI.Control), "Root", null, ChildrenKind.CONTROLS, null);
-               prolog = new StringBuilder ();
-               declarations = new StringBuilder ();
-               script = new StringBuilder ();
-               constructor = new StringBuilder ();
-               init_funcs = new StringBuilder ();
-               epilog = new StringBuilder ();
-               textChunk = new StringBuilder ();
-
-               current_function = new StringBuilder ();
-               functions = new Stack ();
-               functions.Push (current_function);
-
-               parts = new Object [6];
-               parts [0] = prolog;
-               parts [1] = declarations;
-               parts [2] = script;
-               parts [3] = constructor;
-               parts [4] = init_funcs;
-               parts [5] = epilog;
-
-               prolog.Append ("namespace ASP {\n" +
-                             "\tusing System;\n" + 
-                             "\tusing System.Collections;\n" + 
-                             "\tusing System.Collections.Specialized;\n" + 
-                             "\tusing System.Configuration;\n" + 
-                             "\tusing System.IO;\n" + 
-                             "\tusing System.Text;\n" + 
-                             "\tusing System.Text.RegularExpressions;\n" + 
-                             "\tusing System.Web;\n" + 
-                             "\tusing System.Web.Caching;\n" + 
-                             "\tusing System.Web.Security;\n" + 
-                             "\tusing System.Web.SessionState;\n" + 
-                             "\tusing System.Web.UI;\n" + 
-                             "\tusing System.Web.UI.WebControls;\n" + 
-                             "\tusing System.Web.UI.HtmlControls;\n");
-
-               declarations.Append ("\t\tprivate static int __autoHandlers;\n");
-
-               current_function.Append ("\t\tprivate void __BuildControlTree (System.Web.UI.Control __ctrl)\n\t\t{\n");
-               if (!IsUserControl)
-                       current_function.Append ("\t\t\tSystem.Web.UI.IParserAccessor __parser = " + 
-                                                "(System.Web.UI.IParserAccessor) __ctrl;\n\n");
-               else
-                       controls.UseCodeRender = true;
-       }
-
-       public TextReader GetCode ()
-       {
-               if (!parse_ok)
-                       throw new InvalidOperationException ("Parsing not done yet! (may be there were errors?)");
-
-               StringBuilder code = new StringBuilder ();
-               for (int i = 0; i < parts.Length; i++)
-                       code.Append ((StringBuilder) parts [i]);
 
-               return new StringReader (code.ToString ());
-       }
-
-       // Regex.Escape () make some illegal escape sequences for a C# source.
-       private string Escape (string input)
-       {
-               if (input == null)
-                       return String.Empty;
-
-               string output = input.Replace ("\\", "\\\\");
-               output = output.Replace ("\"", "\\\"");
-               output = output.Replace ("\t", "\\t");
-               output = output.Replace ("\r", "\\r");
-               output = output.Replace ("\n", "\\n");
-               output = output.Replace ("\n", "\\n");
-               return output;
-       }
-       
-       bool AddProtectedField (Type type, string fieldName)
-       {
-               if (parentType == null) {
-                       declarations.AppendFormat ("\t\tprotected {0} {1};\n", type.ToString (), fieldName);
-                       return true;
+               void ParseError (ILocation location, string message)
+               {
+                       throw new ParseException (location, message);
                }
 
-               FieldInfo field = parentType.GetField (fieldName, BindingFlags.Public |
-                                                                 BindingFlags.NonPublic |
-                                                                 BindingFlags.Instance |
-                                                                 BindingFlags.Static);
-
-               if (field == null || (!field.IsPublic && !field.IsFamily)) {
-                       declarations.AppendFormat ("\t\tprotected {0} {1};\n", type.ToString (), fieldName);
-                       return true;
-               }
+               void TagParsed (ILocation location, TagType tagtype, string tagid, TagAttributes attributes)
+               {
+                       this.location = location;
+                       if (tparser != null)
+                               tparser.Location = location;
 
-               if (!field.FieldType.IsAssignableFrom (type)) {
-                       string message = String.Format ("The base class includes the field '{0}', but its " +
-                                                       "type '{1}' is not compatible with {2}",
-                                                       fieldName, field.FieldType, type);
+                       if (text.Length != 0)
+                               FlushText ();
 
-                       throw new ApplicationException (message);
-               }
+                       if (0 == String.Compare (tagid, "script", true)) {
+                               if (ProcessScript (tagtype, attributes))
+                                       return;
+                       }
 
-               return false;
-       }
-       
-       private Type LoadParentType (string typeName)
-       {
-               // First try loaded assemblies, then try assemblies in Bin directory.
-               // By now i do this 'by hand' but may be this is a runtime/gac task.
-               Type type = null;
-               Assembly [] assemblies = AppDomain.CurrentDomain.GetAssemblies ();
-               foreach (Assembly ass in assemblies) {
-                       type = ass.GetType (typeName);
-                       if (type != null)
-                               return type;
-               }
+                       switch (tagtype) {
+                       case TagType.Directive:
+                               if (tagid == "")
+                                       tagid = tparser.DefaultDirectiveName;
 
-               Assembly assembly;
-               string [] binDlls = Directory.GetFiles (privateBinPath, "*.dll");
-               foreach (string dll in binDlls) {
-                       string dllPath = Path.Combine (privateBinPath, dll);
-                       assembly = null;
-                       try {
-                               assembly = Assembly.LoadFrom (dllPath);
-                               type = assembly.GetType (typeName);
-                       } catch (Exception e) {
-                               if (assembly != null) {
-                                       Console.WriteLine ("ASP.NET Warning: assembly {0} loaded", dllPath);
-                                       Console.WriteLine ("ASP.NET Warning: but type {0} not found", typeName);
-                               } else {
-                                       Console.WriteLine ("ASP.NET Warning: unable to load type {0} from {1}",
-                                                          typeName, dllPath);
+                               tparser.AddDirective (tagid, attributes.GetDictionary (null));
+                               break;
+                       case TagType.Tag:
+                               if (!ProcessTag (tagid, attributes))
+                                       TextParsed (location, location.PlainText);
+                               break;
+                       case TagType.Close:
+                               if (!CloseControl (tagid))
+                                       TextParsed (location, location.PlainText);
+                               break;
+                       case TagType.SelfClosing:
+                               int count = stack.Count;
+                               if (!ProcessTag (tagid, attributes)) {
+                                       TextParsed (location, location.PlainText);
+                               } else if (stack.Count != count) {
+                                       CloseControl (tagid);
                                }
-                               Console.WriteLine ("ASP.NET Warning: error was: {0}", e.Message);
-                       }
-
-                       if (type != null) {
-                               dependencies.Add (dllPath);
-                               return type;
+                               break;
+                       case TagType.DataBinding:
+                               goto case TagType.CodeRender;
+                       case TagType.CodeRenderExpression:
+                               goto case TagType.CodeRender;
+                       case TagType.CodeRender:
+                               ProcessCode (tagtype, tagid, location);
+                               break;
+                       default:
+                               break;
                        }
+                       //PrintLocation (location);
                }
 
-               return null;
-       }
-
-       private void PageDirective (TagAttributes att)
-       {
-               if (att ["ClassName"] != null){
-                       this.className = (string) att ["ClassName"];
-                       Options ["ClassName"] = className;
-               }
-
-               if (att ["EnableSessionState"] != null){
-                       if (!IsPage)
-                               throw new ApplicationException ("EnableSessionState not allowed here.");
-                       
-                       string est = (string) att ["EnableSessionState"];
-                       if (0 == String.Compare (est, "false", true))
-                               sessionState = SessionState.Disabled;
-                       else if (0 == String.Compare (est, "true", true))
-                               sessionState = SessionState.Enabled;
-                       else if (0 == String.Compare (est, "readonly", true))
-                               sessionState = SessionState.ReadOnly;
-                       else
-                               throw new ApplicationException ("EnableSessionState in Page directive not set to " +
-                                                               "a correct value: " + est);
-               }
-
-               if (att ["Inherits"] != null) {
-                       parent = (string) att ["Inherits"];
-                       parentType = LoadParentType (parent);
-                       if (parentType == null)
-                               throw new ApplicationException ("The class " + parent + " cannot be found.");
+               void TextParsed (ILocation location, string text)
+               {
+                       this.text.Append (text);
+                       //PrintLocation (location);
                }
 
-               if (att ["CompilerOptions"] != null)
-                       Options ["CompilerOptions"] = (string) att ["CompilerOptions"];
-
-               if (att ["AutoEventWireup"] != null) {
-                       if (options ["AutoEventWireup"] != null)
-                               throw new ApplicationException ("Already have an AutoEventWireup attribute");
-                       
-                       bool autoevent = true;
-                       string v = att ["AutoEventWireup"] as string;
-                       try {
-                               autoevent = Convert.ToBoolean (v);
-                       } catch (Exception) {
-                               throw new ApplicationException ("'" + v + "' is not a valid value for AutoEventWireup");
+               void FlushText ()
+               {
+                       string t = text.ToString ();
+                       text.Length = 0;
+                       if (inScript) {
+                               // TODO: store location
+                               tparser.Scripts.Add (t);
+                               return;
                        }
-                       options ["AutoEventWireup"] = autoevent;
-               }
-
-               //FIXME: add support for more attributes.
-       }
-
-       void AddReference (string dll)
-       {
-               string references = Options ["References"] as string;
-               if (references == null)
-                       references = dll;
-               else
-                       references = references + "|" + dll;
-
-               Options ["References"] = references;
-       }
 
-       private void RegisterDirective (TagAttributes att)
-       {
-               string tag_prefix = (string) (att ["tagprefix"] == null ?  "" : att ["tagprefix"]);
-               string name_space = (string) (att ["namespace"] == null ?  "" : att ["namespace"]);
-               string assembly_name = (string) (att ["assembly"] == null ?  "" : att ["assembly"]);
-               string tag_name =  (string) (att ["tagname"] == null ?  "" : att ["tagname"]);
-               string src = (string) (att ["src"] == null ?  "" : att ["src"]);
-
-               if (tag_prefix != "" && name_space != "" && assembly_name != ""){
-                       if (tag_name != "" || src != "")
-                               throw new ApplicationException ("Invalid attributes for @ Register: " +
-                                                               att.ToString ());
-
-                       AddUsing (name_space);
-                       string dll = Path.Combine (privateBinPath, assembly_name + ".dll");
-                       // Hack: it should use assembly.load semantics...
-                       // may be when we don't run mcs as a external program...
-                       if (!File.Exists (dll))
-                               dll = assembly_name;
-                       else
-                               dependencies.Add (dll);
+                       if (tparser.DefaultDirectiveName == "application" && t.Trim () != "")
+                               throw new ParseException (location, "Content not valid for application file.");
 
-                       Foundry.RegisterFoundry (tag_prefix, dll, name_space);
-                       AddReference (dll);
-                       return;
+                       stack.Builder.AppendLiteralString (t);
                }
 
-               if (tag_prefix != "" && tag_name != "" && src != ""){
-                       if (name_space != "" && assembly_name != "")
-                               throw new ApplicationException ("Invalid attributes for @ Register: " +
-                                                               att.ToString ());
+               bool ProcessTag (string tagid, TagAttributes atts)
+               {
+                       ControlBuilder parent = stack.Builder;
+                       ControlBuilder builder = null;
+                       BuilderLocation bl = null;
+                       Hashtable htable = (atts != null) ? atts.GetDictionary (null) : emptyHash;
+                       if (stack.Count > 1)
+                               builder = parent.CreateSubBuilder (tagid, htable, null, tparser, location);
+
+                       if (builder == null && atts != null && atts.IsRunAtServer ())
+                               builder = rootBuilder.CreateSubBuilder (tagid, htable, null, tparser, location);
                        
-                       if (!src.EndsWith (".ascx"))
-                               throw new ApplicationException ("Source file extension for controls " + 
-                                                               "must be .ascx");
-
-                       UserControlData data = GenerateUserControl (src, Context);
-                       switch (data.result) {
-                       case UserControlResult.OK:
-                               AddUsing ("ASP");
-                               Foundry.RegisterFoundry (tag_prefix, tag_name, data.assemblyName, "ASP", data.className);
-                               AddReference (data.assemblyName);
-                               break;
-                       case UserControlResult.FileNotFound:
-                               throw new ApplicationException ("File '" + src + "' not found.");
-                       case UserControlResult.CompilationFailed:
-                               //TODO: should say where the generated .cs file is for the server to
-                               //show the source and the compiler error
-                               throw new NotImplementedException ();
-                       }
-                       return;
-               }
-
-               throw new ApplicationException ("Invalid combination of attributes in " +
-                                               "@ Register: " + att.ToString ());
-       }
-
-       private void ProcessDirective ()
-       {
-               FlushPlainText ();
-               Directive directive = (Directive) current;
-               TagAttributes att = directive.Attributes;
-               if (att == null)
-                       return;
-
-               string value;
-               string id = directive.TagID.ToUpper ();
-               switch (id){
-               case "APPLICATION":
-                       if (main_directive != null)
-                               throw new ApplicationException (id + " not allowed after " + main_directive);
-
-                       if (!IsApplication)
-                               throw new ApplicationException ("@Application not allowed.");
-
-                       string inherits = att ["inherits"] as string;
-                       if (inherits != null) {
-                               parent = inherits;
-                               parentType = LoadParentType (parent);
-                               if (parentType == null)
-                                       throw new ApplicationException ("The class " + parent + " cannot be found.");
-                       }
-
-                       main_directive = directive.TagID;
-                       break;
-               case "PAGE":
-               case "CONTROL":
-                       if (main_directive != null)
-                               throw new ApplicationException (id + " not allowed after " + main_directive);
-
-                       if (IsUserControl && id != "CONTROL")
-                               throw new ApplicationException ("@Page not allowed for user controls.");
-                       else if (IsPage && id != "PAGE")
-                               throw new ApplicationException ("@Control not allowed here. This is a page!");
-
-                       PageDirective (att);
-                       main_directive = directive.TagID;
-                       break;
-               case "IMPORT":
-                       value = att ["namespace"] as string;
-                       if (value == null || att.Count > 1)
-                               throw new ApplicationException ("Wrong syntax in Import directive.");
+                       if (builder == null)
+                               return false;
 
-                       string _using = "using " + value + ";";
-                       if (AddUsing (value) == true) {
-                               string imports = Options ["Import"] as string;
-                               if (imports == null) {
-                                       imports = value;
-                               } else {
-                                       imports += "," + value;
+                       builder.location = location;
+                       builder.ID = htable ["id"] as string;
+                       if (builder.HasBody ()) {
+                               if (builder is TemplateBuilder) {
+                               //      push the id list
                                }
-
-                               Options ["Import"] = imports;
-                       }
-                       break;
-               case "IMPLEMENTS":
-                       if (IsApplication)
-                               throw new ApplicationException ("@ Implements not allowed in an application file.");
-
-                       string iface = (string) att ["interface"];
-                       AddInterface (iface);
-                       break;
-               case "REGISTER":
-                       if (IsApplication)
-                               throw new ApplicationException ("@ Register not allowed in an application file.");
-
-                       RegisterDirective (att);
-                       break;
-               case "ASSEMBLY":
-                       if (att.Count > 1)
-                               throw new ApplicationException ("Wrong syntax in Assembly directive.");
-
-                       string name = att ["name"] as string;
-                       string src = att ["src"] as string;
-
-                       if (name == null && src == null)
-                               throw new ApplicationException ("Wrong syntax in Assembly directive.");
-
-                       if (IsApplication && src != null)
-                               throw new ApplicationException ("'name' attribute expected.");
-
-                       value = (name == null) ? src : name;
-                       string assemblies = Options ["Assembly"] as string;
-                       if (assemblies == null) {
-                               assemblies = value;
+                               stack.Push (builder, location);
                        } else {
-                               assemblies += "," + value;
+                               // FIXME:ObjectTags...
+                               parent.AppendSubBuilder (builder);
+                               builder.CloseControl ();
                        }
 
-                       Options ["Assembly"] = assemblies;
-                       break;
-               }
-       }
-
-       private void ProcessPlainText ()
-       {
-               PlainText asis = (PlainText) current;
-               string trimmed = asis.Text.Trim ();
-               if (trimmed == String.Empty && controls.SpaceBetweenTags == true)
-                       return;
-
-               if (IsApplication) {
-                       if (trimmed != String.Empty)
-                               throw new ApplicationException (app_file_wrong);
-                       return;
-               }
-
-               if (trimmed != String.Empty && controls.PeekChildKind () != ChildrenKind.CONTROLS){
-                       string tag_id = controls.PeekTagID ();
-                       throw new ApplicationException ("Literal content not allowed for " + tag_id);
+                       return true;
                }
-               
-               string escaped_text = Escape (asis.Text);
-               current_function.AppendFormat ("\t\t\t__parser.AddParsedSubObject (" + 
-                                              "new System.Web.UI.LiteralControl (\"{0}\"));\n",
-                                              escaped_text);
-               StringBuilder codeRenderFunction = controls.CodeRenderFunction;
-               codeRenderFunction.AppendFormat ("\t\t\t__output.Write (\"{0}\");\n", escaped_text);
-       }
-
-       private string EnumValueNameToString (Type enum_type, string value_name)
-       {
-               if (value_name.EndsWith ("*"))
-                       throw new ApplicationException ("Invalid property value: '" + value_name + 
-                                                       ". It must be a valid " + enum_type.ToString () + " value.");
 
-               MemberInfo [] nested_types = enum_type.FindMembers (MemberTypes.Field, 
-                                                                   BindingFlags.Public | BindingFlags.Static,
-                                                                   Type.FilterNameIgnoreCase,
-                                                                   value_name);
+               bool ProcessScript (TagType tagtype, TagAttributes attributes)
+               {
+                       if (tagtype != TagType.Close && attributes != null && attributes.IsRunAtServer ()) {
+                               if (tagtype == TagType.Tag) {
+                                       parser.VerbatimID = "script";
+                                       inScript = true;
+                               } //else if (tagtype == TagType.SelfClosing)
+                                       // load script file here
 
-               if (nested_types.Length == 0)
-                       throw new ApplicationException ("Value " + value_name + " not found in enumeration " +
-                                                       enum_type.ToString ());
-               if (nested_types.Length > 1)
-                       throw new ApplicationException ("Value " + value_name + " found " + 
-                                                       nested_types.Length + " in enumeration " +
-                                                       enum_type.ToString ());
+                               return true;
+                       }
 
-               return enum_type.ToString () + "." + nested_types [0].Name;
-       }
-       
-       private void NewControlFunction (string tag_id,
-                                        string control_id,
-                                        Type control_type,
-                                        ChildrenKind children_kind,
-                                        string defaultPropertyName)
-       {
-               ChildrenKind prev_children_kind = controls.PeekChildKind ();
-               if (prev_children_kind == ChildrenKind.NONE || 
-                   prev_children_kind == ChildrenKind.PROPERTIES){
-                       string prev_tag_id = controls.PeekTagID ();
-                       throw new ApplicationException ("Child controls not allowed for " + prev_tag_id);
-               }
+                       bool result = inScript;
+                       inScript = false;
 
-               Type allowed = null;
-               if (prev_children_kind == ChildrenKind.DBCOLUMNS &&
-                   !typeof (DataGridColumn).IsAssignableFrom (control_type)) {
-                       allowed = typeof (DataGridColumn);
-               } else if (prev_children_kind == ChildrenKind.LISTITEM &&
-                        control_type != typeof (System.Web.UI.WebControls.ListItem)) {
-                       allowed = typeof (DataGridColumn);
-               } else if (prev_children_kind == ChildrenKind.HTMLROW) {
-                       Type prevType = controls.PeekType ();
-                       if (prevType == typeof (HtmlTable) && control_type != typeof (HtmlTableRow))
-                               allowed = typeof (HtmlTableRow);
-                       else if (prevType == typeof (Table) && control_type != typeof (TableRow))
-                               allowed = typeof (TableRow);
-               } else if (prev_children_kind == ChildrenKind.HTMLCELL) {
-                       Type prevType = controls.PeekType ();
-                       if (prevType == typeof (HtmlTableRow) && control_type != typeof (HtmlTableCell))
-                               allowed = typeof (HtmlTableCell);
-                       else if (prevType == typeof (TableRow) && control_type != typeof (TableCell))
-                               allowed = typeof (TableCell);
+                       return result;
                }
-       
-               if (allowed != null)
-                       throw new ApplicationException ("Inside " + controls.PeekTagID () + " only " + 
-                                                       allowed + " objects are allowed");
 
-               StringBuilder func_code = new StringBuilder ();
-               current_function = func_code;
-               if (0 == String.Compare (tag_id, "form", true)){
-                       if (has_form_tag)
-                               throw new ApplicationException ("Only one form server tag allowed.");
-                       has_form_tag = true;
-               }
+               bool CloseControl (string tagid)
+               {
+                       ControlBuilder current = stack.Builder;
+                       string btag = current.TagName;
+                       if (0 != String.Compare (tagid, btag, true))
+                               return false;
 
-               controls.Push (control_type, control_id, tag_id, children_kind, defaultPropertyName);
-               bool is_generic = control_type ==  typeof (System.Web.UI.HtmlControls.HtmlGenericControl);
-               functions.Push (current_function);
-               if (control_type != typeof (System.Web.UI.WebControls.ListItem) &&
-                   prev_children_kind != ChildrenKind.DBCOLUMNS) {
-                       current_function.AppendFormat ("\t\tprivate System.Web.UI.Control __BuildControl_" +
-                                                       "{0} ()\n\t\t{{\n\t\t\t{1} __ctrl;\n\n\t\t\t__ctrl" +
-                                                       " = new {1} ({2});\n\t\t\tthis.{0} = __ctrl;\n",
-                                                       control_id, control_type,
-                                                       (is_generic? "\"" + tag_id + "\"" : ""));
-               } else {
-                       current_function.AppendFormat ("\t\tprivate void __BuildControl_{0} ()\n\t\t{{" +
-                                                       "\n\t\t\t{1} __ctrl;\n\t\t\t__ctrl = new {1} ();" +
-                                                       "\n\t\t\tthis.{0} = __ctrl;\n",
-                                                       control_id, control_type);
+                       // if (current is TemplateBuilder)
+                       //      pop from the id list
+                       current.CloseControl ();
+                       stack.Pop ();
+                       stack.Builder.AppendSubBuilder (current);
+                       return true;
                }
 
-               if (children_kind == ChildrenKind.CONTROLS || children_kind == ChildrenKind.OPTION)
-                       current_function.Append ("\t\t\tSystem.Web.UI.IParserAccessor __parser = " + 
-                                                "(System.Web.UI.IParserAccessor) __ctrl;\n");
-       }
-       
-       private void DataBoundProperty (Type target, string varName, string value)
-       {
-               if (value == "")
-                       throw new ApplicationException ("Empty data binding tag.");
+               bool ProcessCode (TagType tagtype, string code, ILocation location)
+               {
+                       ControlBuilder b = null;
+                       if (tagtype == TagType.CodeRender)
+                               b = new CodeRenderBuilder (code, false, location);
+                       else if (tagtype == TagType.CodeRenderExpression)
+                               b = new CodeRenderBuilder (code, true, location);
+                       else if (tagtype == TagType.DataBinding)
+                               b = new DataBindingBuilder (code, location);
+                       else
+                               throw new HttpException ("Should never happen");
 
-               string control_id = controls.PeekControlID ();
-               string control_type_string = controls.PeekType ().ToString ();
-               StringBuilder db_function = controls.DataBindFunction;
-               string container;
-               if (controls.Container == null || !typeof (INamingContainer).IsAssignableFrom (controls.Container))
-                       container = "System.Web.UI.Control";
-               else {
-                       container = controls.Container.ToString ();
+                       stack.Builder.AppendSubBuilder (b);
+                       return true;
                }
 
-               if (db_function.Length == 0)
-                       db_function.AppendFormat ("\t\tpublic void __DataBind_{0} (object sender, " + 
-                                                 "System.EventArgs e) {{\n" +
-                                                 "\t\t\t{1} Container;\n" +
-                                                 "\t\t\t{2} target;\n" +
-                                                 "\t\t\ttarget = ({2}) sender;\n" +
-                                                 "\t\t\tContainer = ({1}) target.BindingContainer;\n",
-                                                 control_id, container, control_type_string);
-
-               /* Removes '<%#' and '%>' */
-               string real_value = value.Remove (0,3);
-               real_value = real_value.Remove (real_value.Length - 2, 2);
-               real_value = real_value.Trim ();
-
-               if (target == typeof (string))
-                       db_function.AppendFormat ("\t\t\ttarget.{0} = System.Convert.ToString ({1});\n",
-                                                 varName, real_value);
-               else
-                       db_function.AppendFormat ("\t\t\ttarget.{0} = ({1}) ({2});\n",
-                                                 varName, target, real_value);
-       }
-
-       /*
-        * Returns true if it generates some code for the specified property
-        */
-       private void AddCodeForPropertyOrField (Type type, string var_name, string att, bool isDataBound)
-       {
-               /* FIXME: should i check for this or let the compiler fail?
-                * if (!prop.CanWrite)
-                *    ....
-                */
-               if (isDataBound) {
-                       DataBoundProperty (type, var_name, att);
+               public ILocation Location {
+                       get { return location; }
                }
-               else if (type == typeof (string)){
-                       if (att == null)
-                               throw new ApplicationException ("null value for attribute " + var_name );
-
-                       current_function.AppendFormat ("\t\t\t__ctrl.{0} = \"{1}\";\n", var_name,
-                                                       Escape (att)); // FIXME: really Escape this?
-               } 
-               else if (type.IsEnum){
-                       if (att == null)
-                               throw new ApplicationException ("null value for attribute " + var_name );
-
-                       string enum_value = EnumValueNameToString (type, att);
-
-                       current_function.AppendFormat ("\t\t\t__ctrl.{0} = {1};\n", var_name, enum_value);
-               } 
-               else if (type == typeof (bool)){
-                       string value;
-                       if (att == null)
-                               value = "true"; //FIXME: is this ok for non Style properties?
-                       else if (0 == String.Compare (att, "true", true))
-                               value = "true";
-                       else if (0 == String.Compare (att, "false", true))
-                               value = "false";
-                       else
-                               throw new ApplicationException ("Value '" + att  + "' is not a valid boolean.");
-
-                       current_function.AppendFormat ("\t\t\t__ctrl.{0} = {1};\n", var_name, value);
-               }
-               else if (type == typeof (System.Web.UI.WebControls.Unit)){
-                        //FIXME: should use the culture specified in Page
-                       try {
-                               Unit value = Unit.Parse (att, System.Globalization.CultureInfo.InvariantCulture);
-                       } catch (Exception) {
-                               throw new ApplicationException ("'" + att + "' cannot be parsed as a unit.");
-                       }
-                       current_function.AppendFormat ("\t\t\t__ctrl.{0} = " + 
-                                                       "System.Web.UI.WebControls.Unit.Parse (\"{1}\", " + 
-                                                       "System.Globalization.CultureInfo.InvariantCulture);\n", 
-                                                       var_name, att);
-               }
-               else if (type == typeof (System.Web.UI.WebControls.FontUnit)){
-                        //FIXME: should use the culture specified in Page
-                       try {
-                               FontUnit value = FontUnit.Parse (att, System.Globalization.CultureInfo.InvariantCulture);
-                       } catch (Exception) {
-                               throw new ApplicationException ("'" + att + "' cannot be parsed as a unit.");
-                       }
-                       current_function.AppendFormat ("\t\t\t__ctrl.{0} = " + 
-                                                       "System.Web.UI.WebControls.FontUnit.Parse (\"{1}\", " + 
-                                                       "System.Globalization.CultureInfo.InvariantCulture);\n", 
-                                                       var_name, att);
-               }
-               else if (type == typeof (Int16) || type == typeof (Int32) || type == typeof (Int64)) {
-                       long value;
-                       try {
-                               value = Int64.Parse (att); //FIXME: should use the culture specified in Page
-                       } catch (Exception){
-                               throw new ApplicationException (att + " is not a valid signed number " + 
-                                                               "or is out of range.");
-                       }
-
-                       current_function.AppendFormat ("\t\t\t__ctrl.{0} = {1};\n", var_name, value);
-               }
-               else if (type == typeof (UInt16) || type == typeof (UInt32) || type == typeof (UInt64)) {
-                       ulong value;
-                       try {
-                               value = UInt64.Parse (att); //FIXME: should use the culture specified in Page
-                       } catch (Exception){
-                               throw new ApplicationException (att + " is not a valid unsigned number " + 
-                                                               "or is out of range.");
-                       }
-
-                       current_function.AppendFormat ("\t\t\t__ctrl.{0} = {1};\n", var_name, value);
-               }
-               else if (type == typeof (float)) {
-                       float value;
-                       try {
-                               value = Single.Parse (att);
-                       } catch (Exception){
-                               throw new ApplicationException (att + " is not  avalid float number or " +
-                                                               "is out of range.");
-                       }
-
-                       current_function.AppendFormat ("\t\t\t__ctrl.{0} = {1};\n", var_name, value);
-               }
-               else if (type == typeof (double)){
-                       double value;
-                       try {
-                               value = Double.Parse (att);
-                       } catch (Exception){
-                               throw new ApplicationException (att + " is not  avalid double number or " +
-                                                               "is out of range.");
-                       }
-
-                       current_function.AppendFormat ("\t\t\t__ctrl.{0} = {1};\n", var_name, value);
-               }
-               else if (type == typeof (System.Drawing.Color)){
-                       Color c;
-                       try {
-                               c = (Color) TypeDescriptor.GetConverter (typeof (Color)).ConvertFromString (att);
-                       } catch (Exception e){
-                               throw new ApplicationException ("Color " + att + " is not a valid color.", e);
-                       }
-
-                       // Should i also test for IsSystemColor?
-                       // Are KnownColor members in System.Drawing.Color?
-                       if (c.IsKnownColor){
-                               current_function.AppendFormat ("\t\t\t__ctrl.{0} = System.Drawing.Color." +
-                                                              "{1};\n", var_name, c.Name);
-                       }
-                       else {
-                               current_function.AppendFormat ("\t\t\t__ctrl.{0} = System.Drawing.Color." +
-                                                              "FromArgb ({1}, {2}, {3}, {4});\n",
-                                                              var_name, c.A, c.R, c.G, c.B);
-                       }
-               }
-               else if (type == typeof (string [])) {
-                       string [] subStrings = att.Split (',');
-                       current_function.AppendFormat ("\t\t\t__ctrl.{0} = new String [] {{\n", var_name);
-                       int end = subStrings.Length;
-                       for (int i = 0; i < end; i++) {
-                               string s = subStrings [i].Trim ();
-                               current_function.AppendFormat ("\t\t\t\t\"{0}\"", s);
-                               if (i == end - 1)
-                                       current_function.Append ("\t\t\t\t};\n");
-                               else
-                                       current_function.Append (",\n");
-                       }
-               } else {
-                       throw new ApplicationException ("Unsupported type in property: " + 
-                                                       type.ToString ());
-               }
-       }
-
-       private bool ProcessPropertiesAndFields (MemberInfo member, string id, TagAttributes att)
-       {
-               int hyphen = id.IndexOf ('-');
-
-               bool isPropertyInfo = (member is PropertyInfo);
-
-               bool is_processed = false;
-               bool isDataBound = att.IsDataBound ((string) att [id]);
-               Type type;
-               if (isPropertyInfo) {
-                       type = ((PropertyInfo) member).PropertyType;
-                       if (hyphen == -1 && ((PropertyInfo) member).CanWrite == false)
-                               return false;
-               } else {
-                       type = ((FieldInfo) member).FieldType;
-               }
-
-               if (0 == String.Compare (member.Name, id, true)){
-                       AddCodeForPropertyOrField (type, member.Name, (string) att [id], isDataBound);
-                       is_processed = true;
-               } else if (hyphen != -1 && (type == fontinfoType || type == styleType || type.IsSubclassOf (styleType))){
-                       string prop_field = id.Replace ("-", ".");
-                       string [] parts = prop_field.Split (new char [] {'.'});
-                       if (parts.Length != 2 || 0 != String.Compare (member.Name, parts [0], true))
-                               return false;
-
-                       PropertyInfo [] subprops = type.GetProperties ();
-                       foreach (PropertyInfo subprop in subprops){
-                               if (0 != String.Compare (subprop.Name, parts [1], true))
-                                       continue;
-
-                               if (subprop.CanWrite == false)
-                                       return false;
-
-                               bool is_bool = subprop.PropertyType == typeof (bool);
-                               if (!is_bool && att [id] == null){
-                                       att [id] = ""; // Font-Size -> Font-Size="" as html
-                                       return false;
-                               }
-
-                               string value;
-                               if (att [id] == null && is_bool)
-                                       value = "true"; // Font-Bold <=> Font-Bold="true"
-                               else
-                                       value = (string) att [id];
-
-                               AddCodeForPropertyOrField (subprop.PropertyType,
-                                                member.Name + "." + subprop.Name,
-                                                value, isDataBound);
-                               is_processed = true;
-                       }
-               }
-
-               return is_processed;
-       }
-       
-       private void AddCodeForAttributes (Type type, TagAttributes att)
-       {
-               EventInfo [] ev_info = type.GetEvents ();
-               PropertyInfo [] prop_info = type.GetProperties ();
-               FieldInfo [] field_info = type.GetFields ();
-               bool is_processed = false;
-               ArrayList processed = new ArrayList ();
-
-               foreach (string id in att.Keys){
-                       if (0 == String.Compare (id, "runat", true) || 0 == String.Compare (id, "id", true))
-                               continue;
-
-                       if (id.Length > 2 && id.Substring (0, 2).ToUpper () == "ON"){
-                               string id_as_event = id.Substring (2);
-                               foreach (EventInfo ev in ev_info){
-                                       if (0 == String.Compare (ev.Name, id_as_event, true)){
-                                               current_function.AppendFormat (
-                                                               "\t\t\t__ctrl.{0} += " + 
-                                                               "new {1} (this.{2});\n", 
-                                                               ev.Name, ev.EventHandlerType, att [id]);
-                                               is_processed = true;
-                                               break;
-                                       }
-                               }
-                               if (is_processed){
-                                       is_processed = false;
-                                       continue;
-                               }
-                       } 
-
-                       foreach (PropertyInfo prop in prop_info){
-                               is_processed = ProcessPropertiesAndFields (prop, id, att);
-                               if (is_processed)
-                                       break;
-                       }
-
-                       if (!is_processed) {
-                               foreach (FieldInfo field in field_info){
-                                       is_processed = ProcessPropertiesAndFields (field, id, att);
-                                       if (is_processed)
-                                               break;
-                               }
-                       }
-
-                       if (is_processed){
-                               is_processed = false;
-                               continue;
-                       }
-
-                       current_function.AppendFormat ("\t\t\t((System.Web.UI.IAttributeAccessor) __ctrl)." +
-                                               "SetAttribute (\"{0}\", \"{1}\");\n",
-                                               id, Escape ((string) att [id]));
-               }
-       }
-       
-       private void AddCodeRenderControl (StringBuilder function)
-       {
-               AddCodeRenderControl (function, controls.CodeRenderIndex);
-       }
-
-       private void AddCodeRenderControl (StringBuilder function, int index)
-       {
-               function.AppendFormat ("\t\t\tparameterContainer.Controls [{0}]." + 
-                                      "RenderControl (__output);\n", index);
-       }
-
-       private void AddRenderMethodDelegate (StringBuilder function, string control_id)
-       {
-               function.AppendFormat ("\t\t\t__ctrl.SetRenderMethodDelegate (new System.Web." + 
-                                      "UI.RenderMethod (this.__Render_{0}));\n", control_id);
-       }
-
-       private void AddCodeRenderFunction (string codeRender, string control_id)
-       {
-               StringBuilder codeRenderFunction = new StringBuilder ();
-               codeRenderFunction.AppendFormat ("\t\tprivate void __Render_{0} " + 
-                                                "(System.Web.UI.HtmlTextWriter __output, " + 
-                                                "System.Web.UI.Control parameterContainer)\n" +
-                                                "\t\t{{\n", control_id);
-               codeRenderFunction.Append (codeRender);
-               codeRenderFunction.Append ("\t\t}\n\n");
-               init_funcs.Append (codeRenderFunction);
-       }
-
-       private void RemoveLiterals (StringBuilder function)
-       {
-               string no_literals = Regex.Replace (function.ToString (),
-                                                   @"\t\t\t__parser.AddParsedSubObject \(" + 
-                                                   @"new System.Web.UI.LiteralControl \(.+\);\n", "");
-               function.Length = 0;
-               function.Append (no_literals);
-       }
-
-       private bool FinishControlFunction (string tag_id)
-       {
-               if (functions.Count == 0)
-                       throw new ApplicationException ("Unbalanced open/close tags");
-
-               if (controls.Count == 0)
-                       return false;
-
-               string saved_id = controls.PeekTagID ();
-               if (0 != String.Compare (saved_id, tag_id, true))
-                       return false;
-
-               FlushPlainText ();
-               StringBuilder old_function = (StringBuilder) functions.Pop ();
-               current_function = (StringBuilder) functions.Peek ();
-
-               string control_id = controls.PeekControlID ();
-               Type control_type = controls.PeekType ();
-               ChildrenKind child_kind = controls.PeekChildKind ();
-
-               bool hasDataBindFunction = controls.HasDataBindFunction ();
-               if (hasDataBindFunction)
-                       old_function.AppendFormat ("\t\t\t__ctrl.DataBinding += new System.EventHandler " +
-                                                  "(this.__DataBind_{0});\n", control_id);
-
-               bool useCodeRender = controls.UseCodeRender;
-               if (useCodeRender)
-                       AddRenderMethodDelegate (old_function, control_id);
-               
-               if (control_type == typeof (System.Web.UI.ITemplate)){
-                       old_function.Append ("\n\t\t}\n\n");
-                       current_function.AppendFormat ("\t\t\t__ctrl.{0} = new System.Web.UI." + 
-                                                      "CompiledTemplateBuilder (new System.Web.UI." +
-                                                      "BuildTemplateMethod (this.__BuildControl_{1}));\n",
-                                                      saved_id, control_id);
-               }
-               else if (control_type == typeof (System.Web.UI.WebControls.DataGridColumnCollection)){
-                       old_function.Append ("\n\t\t}\n\n");
-                       current_function.AppendFormat ("\t\t\tthis.__BuildControl_{0} (__ctrl.{1});\n",
-                                                       control_id, saved_id);
-               }
-               else if (control_type == typeof (System.Web.UI.WebControls.DataGridColumn) ||
-                        control_type.IsSubclassOf (typeof (System.Web.UI.WebControls.DataGridColumn)) ||
-                        control_type == typeof (System.Web.UI.WebControls.ListItem)){
-                       old_function.Append ("\n\t\t}\n\n");
-                       string parsed = "";
-                       string ctrl_name = "ctrl";
-                       Type cont = controls.Container;
-                       if (cont == null || cont == typeof (System.Web.UI.HtmlControls.HtmlSelect)){
-                               parsed = "ParsedSubObject";
-                               ctrl_name = "parser";
-                       }
-
-                       current_function.AppendFormat ("\t\t\tthis.__BuildControl_{0} ();\n" +
-                                                      "\t\t\t__{1}.Add{2} (this.{0});\n\n",
-                                                      control_id, ctrl_name, parsed);
-               }
-               else if (child_kind == ChildrenKind.LISTITEM){
-                       old_function.Append ("\n\t\t}\n\n");
-                       init_funcs.Append (old_function); // Closes the BuildList function
-                       old_function = (StringBuilder) functions.Pop ();
-                       current_function = (StringBuilder) functions.Peek ();
-                       old_function.AppendFormat ("\n\t\t\tthis.__BuildControl_{0} (__ctrl.{1});\n\t\t\t" +
-                                                  "return __ctrl;\n\t\t}}\n\n",
-                                                  control_id, controls.PeekDefaultPropertyName ());
-
-                       controls.Pop ();
-                       control_id = controls.PeekControlID ();
-                       current_function.AppendFormat ("\t\t\tthis.__BuildControl_{0} ();\n\t\t\t__parser." +
-                                                      "AddParsedSubObject (this.{0});\n\n", control_id);
-               } else if (control_type == typeof (HtmlTableCell) || control_type == typeof (TableCell)) {
-                       old_function.Append ("\n\t\t\treturn __ctrl;\n\t\t}\n\n");
-                       object top = controls.Pop ();
-                       Type t = controls.PeekType ();
-                       controls.Push (top);
-                       string parsed = "";
-                       string ctrl_name = "ctrl";
-                       if (!t.IsSubclassOf (typeof (WebControl)) && t != typeof (HtmlTableRow)) {
-                               parsed = "ParsedSubObject";
-                               ctrl_name = "parser";
-                       }
-
-                       current_function.AppendFormat ("\t\t\tthis.__BuildControl_{0} ();\n" +
-                                                      "\t\t\t__{1}.Add{2} (this.{0});\n\n",
-                                                      control_id, ctrl_name, parsed);
-               } else if (child_kind == ChildrenKind.HTMLROW || child_kind == ChildrenKind.HTMLCELL) {
-                       old_function.Append ("\n\t\t}\n\n");
-                       init_funcs.Append (old_function);
-                       old_function = (StringBuilder) functions.Pop ();
-                       current_function = (StringBuilder) functions.Peek ();
-                       old_function.AppendFormat ("\n\t\t\tthis.__BuildControl_{0} (__ctrl.{1});\n\t\t\t" +
-                                                  "return __ctrl;\n\t\t}}\n\n",
-                                                  control_id, controls.PeekDefaultPropertyName ());
-
-                       controls.Pop ();
-                       control_id = controls.PeekControlID ();
-                       current_function.AppendFormat ("\t\t\tthis.__BuildControl_{0} ();\n", control_id);
-                       if (child_kind == ChildrenKind.HTMLROW) {
-                               current_function.AppendFormat ("\t\t\t__parser.AddParsedSubObject ({0});\n",
-                                                               control_id);
-                       } else {
-                               current_function.AppendFormat ("\t\t\t__ctrl.Add (this.{0});\n", control_id);
-                       }
-               } else {
-                       old_function.Append ("\n\t\t\treturn __ctrl;\n\t\t}\n\n");
-                       current_function.AppendFormat ("\t\t\tthis.__BuildControl_{0} ();\n\t\t\t__parser." +
-                                                      "AddParsedSubObject (this.{0});\n\n", control_id);
-               }
-
-               if (useCodeRender)
-                       RemoveLiterals (old_function);
-
-               init_funcs.Append (old_function);
-               if (useCodeRender)
-                       AddCodeRenderFunction (controls.CodeRenderFunction.ToString (), control_id);
-               
-               if (hasDataBindFunction){
-                       StringBuilder db_function = controls.DataBindFunction;
-                       db_function.Append ("\t\t}\n\n");
-                       init_funcs.Append (db_function);
-               }
-
-               // Avoid getting empty stacks for unbalanced open/close tags
-               if (controls.Count > 1){
-                       controls.Pop ();
-                       AddCodeRenderControl (controls.CodeRenderFunction, controls.ChildIndex);
-               }
-
-               return true;
-       }
-
-       private void NewTableElementFunction (HtmlControlTag ctrl)
-       {
-               string control_id = Tag.GetDefaultID ();
-               ChildrenKind child_kind;
-
-               Type t;
-               if (ctrl.ControlType == typeof (HtmlTable)) {
-                       t = typeof (HtmlTableRowCollection);
-                       child_kind = ChildrenKind.HTMLROW;
-               } else {
-                       t = typeof (HtmlTableCellCollection);
-                       child_kind = ChildrenKind.HTMLCELL;
-               }
-
-               controls.Push (ctrl.ControlType,
-                              control_id,
-                              ctrl.TagID,
-                              child_kind,
-                              ctrl.ParseChildren);
-
-               current_function = new StringBuilder ();
-               functions.Push (current_function);
-               current_function.AppendFormat ("\t\tprivate void __BuildControl_{0} ({1} __ctrl)\n" +
-                                               "\t\t{{\n", control_id, t);
-       }
-
-       private void ProcessHtmlControlTag ()
-       {
-               FlushPlainText ();
-               HtmlControlTag html_ctrl = (HtmlControlTag) current;
-               if (html_ctrl.TagID.ToUpper () == "SCRIPT"){
-                       //FIXME: if the is script is to be read from disk, do it!
-                       if (html_ctrl.SelfClosing)
-                               throw new ApplicationException ("Read script from file not supported yet.");
-
-                       sstatus = ScriptStatus.Open;
-                       return;
-               }
-               
-               if (IsApplication)
-                       throw new ApplicationException (app_file_wrong);
-               
-               Type controlType = html_ctrl.ControlType;
-               AddProtectedField (controlType, html_ctrl.ControlID);
-
-               ChildrenKind children_kind;
-               if (0 == String.Compare (html_ctrl.TagID, "table", true))
-                       children_kind = ChildrenKind.HTMLROW;
-               else if (0 == String.Compare (html_ctrl.TagID, "tr", true))
-                       children_kind = ChildrenKind.HTMLCELL;
-               else if (0 != String.Compare (html_ctrl.TagID, "select", true))
-                       children_kind = html_ctrl.IsContainer ? ChildrenKind.CONTROLS :
-                                                               ChildrenKind.NONE;
-               else
-                       children_kind = ChildrenKind.OPTION;
-
-               NewControlFunction (html_ctrl.TagID, html_ctrl.ControlID, controlType, children_kind, html_ctrl.ParseChildren); 
-
-               current_function.AppendFormat ("\t\t\t__ctrl.ID = \"{0}\";\n", html_ctrl.ControlID);
-               AddCodeForAttributes (html_ctrl.ControlType, html_ctrl.Attributes);
-
-               if (children_kind == ChildrenKind.HTMLROW || children_kind == ChildrenKind.HTMLCELL)
-                       NewTableElementFunction (html_ctrl);
-
-               if (html_ctrl.SelfClosing)
-                       FinishControlFunction (html_ctrl.TagID);
-       }
-
-       // Closing is performed in FinishControlFunction ()
-       private void NewBuildListFunction (AspComponent component)
-       {
-               string control_id = Tag.GetDefaultID ();
-
-               controls.Push (component.ComponentType,
-                              control_id, 
-                              component.TagID, 
-                              component.ChildrenKind, 
-                              component.DefaultPropertyName);
-
-               Type childType = component.DefaultPropertyType;
-               if (childType == null)
-                       childType = typeof (ListItemCollection);
-
-               current_function = new StringBuilder ();
-               functions.Push (current_function);
-               current_function.AppendFormat ("\t\tprivate void __BuildControl_{0} " +
-                                               "({1} __ctrl)\n" +
-                                               "\t\t{{\n", control_id, childType);
-       }
-
-       private void ProcessComponent ()
-       {
-               FlushPlainText ();
-               AspComponent component = (AspComponent) current;
-               Type component_type = component.ComponentType;
-               AddProtectedField (component_type, component.ControlID);
-
-               NewControlFunction (component.TagID, component.ControlID, component_type,
-                                   component.ChildrenKind, component.DefaultPropertyName); 
-
-               if (component_type == typeof (UserControl) ||
-                   component_type.IsSubclassOf (typeof (System.Web.UI.UserControl)))
-                       current_function.Append ("\t\t\t__ctrl.InitializeAsUserControl (Page);\n");
-
-               if (component_type == typeof (Control) ||
-                   component_type.IsSubclassOf (typeof (System.Web.UI.Control)))
-                       current_function.AppendFormat ("\t\t\t__ctrl.ID = \"{0}\";\n", component.ControlID);
-
-               AddCodeForAttributes (component.ComponentType, component.Attributes);
-               if (component.ChildrenKind == ChildrenKind.LISTITEM || component.DefaultPropertyType != null)
-                       NewBuildListFunction (component);
-
-               if (component.SelfClosing)
-                       FinishControlFunction (component.TagID);
-       }
-
-       private void ProcessServerObjectTag ()
-       {
-               FlushPlainText ();
-               ServerObjectTag obj = (ServerObjectTag) current;
-               declarations.AppendFormat ("\t\tprivate {0} cached{1};\n", obj.ObjectClass, obj.ObjectID);
-               constructor.AppendFormat ("\n\t\tprivate {0} {1}\n\t\t{{\n\t\t\tget {{\n\t\t\t\t" + 
-                                         "if (this.cached{1} == null)\n\t\t\t\t\tthis.cached{1} = " + 
-                                         "new {0} ();\n\t\t\t\treturn cached{1};\n\t\t\t}}\n\t\t}}\n\n",
-                                         obj.ObjectClass, obj.ObjectID);
-       }
-
-       // Creates a new function that sets the values of subproperties.
-       private void NewStyleFunction (PropertyTag tag)
-       {
-               current_function = new StringBuilder ();
-
-               string prop_id = tag.PropertyID;
-               Type prop_type = tag.PropertyType;
-               // begin function
-               current_function.AppendFormat ("\t\tprivate void __BuildControl_{0} ({1} __ctrl)\n" +
-                                               "\t\t{{\n", prop_id, prop_type);
-               
-               // Add property initialization code
-               PropertyInfo [] subprop_info = prop_type.GetProperties ();
-               TagAttributes att = tag.Attributes;
-
-               string subprop_name = null;
-               foreach (string id in att.Keys){
-                       if (0 == String.Compare (id, "runat", true) || 0 == String.Compare (id, "id", true))
-                               continue;
-
-                       bool is_processed = false;
-                       foreach (PropertyInfo subprop in subprop_info){
-                               is_processed = ProcessPropertiesAndFields (subprop, id, att);
-                               if (is_processed){
-                                       subprop_name = subprop.Name;
-                                       break;
-                               }
-                       }
-
-                       if (subprop_name == null)
-                               throw new ApplicationException ("Property " + tag.TagID + " does not have " + 
-                                                               "a " + id + " subproperty.");
-               }
-
-               // Finish function
-               current_function.Append ("\n\t\t}\n\n");
-               init_funcs.Append (current_function);
-               current_function = (StringBuilder) functions.Peek ();
-               current_function.AppendFormat ("\t\t\tthis.__BuildControl_{0} (__ctrl.{1});\n",
-                                               prop_id, tag.PropertyName);
-
-               if (!tag.SelfClosing){
-                       // Next tag should be the closing tag
-                       controls.Push (null, null, null, ChildrenKind.NONE, null);
-                       waitClosing = tag.TagID;
-               }
-       }
-
-       // This one just opens the function. Closing is performed in FinishControlFunction ()
-       private void NewTemplateFunction (PropertyTag tag)
-       {
-               /*
-                * FIXME
-                * This function does almost the same as NewControlFunction.
-                * Consider merging.
-                */
-               string prop_id = tag.PropertyID;
-               Type prop_type = tag.PropertyType;
-               string tag_id = tag.PropertyName; // Real property name used in FinishControlFunction
-
-               controls.Push (prop_type, prop_id, tag_id, ChildrenKind.CONTROLS, null);
-               current_function = new StringBuilder ();
-               functions.Push (current_function);
-               current_function.AppendFormat ("\t\tprivate void __BuildControl_{0} " +
-                                               "(System.Web.UI.Control __ctrl)\n" +
-                                               "\t\t{{\n" +
-                                               "\t\t\tSystem.Web.UI.IParserAccessor __parser " + 
-                                               "= (System.Web.UI.IParserAccessor) __ctrl;\n" , prop_id);
-       }
-
-       // Closing is performed in FinishControlFunction ()
-       private void NewDBColumnFunction (PropertyTag tag)
-       {
-               /*
-                * FIXME
-                * This function also does almost the same as NewControlFunction.
-                * Consider merging.
-                */
-               string prop_id = tag.PropertyID;
-               Type prop_type = tag.PropertyType;
-               string tag_id = tag.PropertyName; // Real property name used in FinishControlFunction
-
-               controls.Push (prop_type, prop_id, tag_id, ChildrenKind.DBCOLUMNS, null);
-               current_function = new StringBuilder ();
-               functions.Push (current_function);
-               current_function.AppendFormat ("\t\tprivate void __BuildControl_{0} " +
-                                               "(System.Web.UI.WebControls.DataGridColumnCollection __ctrl)\n" +
-                                               "\t\t{{\n", prop_id);
-       }
-
-       private void NewPropertyFunction (PropertyTag tag)
-       {
-               FlushPlainText ();
-               if (tag.PropertyType == typeof (System.Web.UI.WebControls.Style) ||
-                   tag.PropertyType.IsSubclassOf (typeof (System.Web.UI.WebControls.Style)))
-                       NewStyleFunction (tag);
-               else if (tag.PropertyType == typeof (System.Web.UI.ITemplate))
-                       NewTemplateFunction (tag);
-               else if (tag.PropertyType == typeof (System.Web.UI.WebControls.DataGridColumnCollection))
-                       NewDBColumnFunction (tag);
-               else
-                       throw new ApplicationException ("Other than Style and ITemplate not supported yet. " + 
-                                                       tag.PropertyType);
-       }
-       
-       private void ProcessHtmlTag ()
-       {
-               Tag tag = (Tag) current;
-               ChildrenKind child_kind = controls.PeekChildKind ();
-               if (child_kind == ChildrenKind.NONE){
-                       string tag_id = controls.PeekTagID ();
-                       throw new ApplicationException (tag + " not allowed inside " + tag_id);
-               }
-                                       
-               if (child_kind == ChildrenKind.OPTION){
-                       if (0 != String.Compare (tag.TagID, "option", true))
-                               throw new ApplicationException ("Only <option> tags allowed inside <select>.");
-
-                       string default_id = Tag.GetDefaultID ();
-                       Type type = typeof (System.Web.UI.WebControls.ListItem);
-                       AddProtectedField (type, default_id);
-                       NewControlFunction (tag.TagID, default_id, type, ChildrenKind.CONTROLS, null); 
-                       return;
-               }
-
-               if (child_kind == ChildrenKind.CONTROLS) {
-                       ArrayList tag_elements = tag.GetElements ();
-                       foreach (Element e in tag_elements) {
-                               if (e is PlainText) {
-                                       current = e;
-                                       textChunk.Append (((PlainText) e).Text);
-                               } else if (e is CodeRenderTag) {
-                                       current = e;
-                                       ProcessCodeRenderTag ();
-                               } else if (e is DataBindingTag) {
-                                       current = e;
-                                       ProcessDataBindingLiteral ();
-                               } else {
-                                       throw new ApplicationException (fullPath + ": unexpected tag type " + e.GetType ());
-                               }
-                       }
-                       return;
-               }
-
-               if (child_kind == ChildrenKind.HTMLROW) {
-                       if (0 == String.Compare (tag.TagID, "tr", true)) {
-                               current = new HtmlControlTag (tag);
-                               ProcessHtmlControlTag ();
-                               return;
-                       }
-               }
-
-               if (child_kind == ChildrenKind.HTMLCELL) {
-                       if (0 == String.Compare (tag.TagID, "td", true)) {
-                               current = new HtmlControlTag (tag);
-                               ProcessHtmlControlTag ();
-                               return;
-                       }
-               }
-
-               // Now child_kind should be PROPERTIES, so only allow tag_id == property
-               Type control_type = controls.PeekType ();
-               PropertyInfo [] prop_info = control_type.GetProperties ();
-               bool is_processed = false;
-               foreach (PropertyInfo prop in prop_info){
-                       if (0 == String.Compare (prop.Name, tag.TagID, true)){
-                               PropertyTag prop_tag = new PropertyTag (tag, prop.PropertyType, prop.Name);
-                               NewPropertyFunction (prop_tag);
-                               is_processed = true;
-                               break;
-                       }
-               }
-               
-               if (!is_processed){
-                       string tag_id = controls.PeekTagID ();
-                       throw new ApplicationException (tag.TagID + " is not a property of " + control_type);
-               }
-       }
-
-       private Tag Map (Tag tag)
-       {
-               int pos = tag.TagID.IndexOf (":");
-               if (pos == -1) {
-                       ChildrenKind child_kind = controls.PeekChildKind ();
-                       if (child_kind == ChildrenKind.HTMLROW && 0 == String.Compare (tag.TagID, "tr", true)) {
-                               tag.Attributes.Add ("runat", "server");
-                               return new HtmlControlTag (tag);
-                       } else if (child_kind == ChildrenKind.HTMLROW && 0 == String.Compare (tag.TagID, "tr", true)) {
-                               tag.Attributes.Add ("runat", "server");
-                               return new HtmlControlTag (tag);
-                       }
-               }
-
-               if (tag is CloseTag ||
-                   ((tag.Attributes == null || 
-                   !tag.Attributes.IsRunAtServer ()) && pos == -1))
-                       return tag;
-
-               if (pos == -1){
-                       if (0 == String.Compare (tag.TagID, "object", true))
-                               return new ServerObjectTag (tag);
-
-                       return new HtmlControlTag (tag);
-               }
-
-               string foundry_name = tag.TagID.Substring (0, pos);
-               string component_name = tag.TagID.Substring (pos + 1);
-
-               if (Foundry.LookupFoundry (foundry_name) == false)
-                       throw new ApplicationException ("Cannot find foundry for alias'" + foundry_name + "'");
-
-               AspComponent component = Foundry.MakeAspComponent (foundry_name, component_name, tag);
-               if (component == null)
-                       throw new ApplicationException ("Cannot find component '" + component_name + 
-                                                       "' for alias '" + foundry_name + "'");
-
-               return component;
-       }
-       
-       private void ProcessCloseTag ()
-       {
-               CloseTag closeTag = (CloseTag) current;
-               if (FinishControlFunction (closeTag.TagID))
-                       return;
-
-               textChunk.Append (closeTag.PlainHtml);
-       }
-
-       private void ProcessDataBindingLiteral ()
-       {
-               FlushPlainText ();
-               DataBindingTag dataBinding = (DataBindingTag) current;
-               string actual_value = dataBinding.Data;
-               if (actual_value == "")
-                       throw new ApplicationException ("Empty data binding tag.");
-
-               if (controls.PeekChildKind () != ChildrenKind.CONTROLS)
-                       throw new ApplicationException ("Data bound content not allowed for " + 
-                                                       controls.PeekTagID ());
-
-               StringBuilder db_function = new StringBuilder ();
-               string control_id = Tag.GetDefaultID ();
-               string control_type_string = "System.Web.UI.DataBoundLiteralControl";
-               AddProtectedField (typeof (System.Web.UI.DataBoundLiteralControl), control_id);
-               // Build the control
-               db_function.AppendFormat ("\t\tprivate System.Web.UI.Control __BuildControl_{0} ()\n" +
-                                         "\t\t{{\n\t\t\t{1} __ctrl;\n\n" +
-                                         "\t\t\t__ctrl = new {1} (0, 1);\n" + 
-                                         "\t\t\tthis.{0} = __ctrl;\n" +
-                                         "\t\t\t__ctrl.DataBinding += new System.EventHandler " + 
-                                         "(this.__DataBind_{0});\n" +
-                                         "\t\t\treturn __ctrl;\n"+
-                                         "\t\t}}\n\n",
-                                         control_id, control_type_string);
-               // DataBinding handler
-               db_function.AppendFormat ("\t\tpublic void __DataBind_{0} (object sender, " + 
-                                         "System.EventArgs e) {{\n" +
-                                         "\t\t\t{1} Container;\n" +
-                                         "\t\t\t{2} target;\n" +
-                                         "\t\t\ttarget = ({2}) sender;\n" +
-                                         "\t\t\tContainer = ({1}) target.BindingContainer;\n" +
-                                         "\t\t\ttarget.SetDataBoundString (0, System.Convert." +
-                                         "ToString ({3}));\n" +
-                                         "\t\t}}\n\n",
-                                         control_id, controls.Container, control_type_string,
-                                         actual_value);
-
-               init_funcs.Append (db_function);
-               current_function.AppendFormat ("\t\t\tthis.__BuildControl_{0} ();\n\t\t\t__parser." +
-                                              "AddParsedSubObject (this.{0});\n\n", control_id);
-
-               AddCodeRenderControl (controls.CodeRenderFunction);
-       }
-
-       private void ProcessCodeRenderTag ()
-       {
-               FlushPlainText ();
-               CodeRenderTag code_tag = (CodeRenderTag) current;
-
-               controls.UseCodeRender = true;
-               if (code_tag.IsVarName)
-                       controls.CodeRenderFunction.AppendFormat ("\t\t\t__output.Write ({0});\n",
-                                                                 code_tag.Code);
-               else
-                       controls.CodeRenderFunction.AppendFormat ("\t\t\t{0}\n", code_tag.Code);
-       }
-       
-       void FlushPlainText ()
-       {
-               if (textChunk.Length != 0) {
-                       Element saved = current;
-                       current = new PlainText (textChunk.ToString ());
-                       textChunk.Length = 0;
-                       ProcessPlainText ();
-                       current = saved;
-               }
-       }
-       
-       void ParseError (string msg, int line, int col)
-       {
-               throw new ParseException (fullPath, msg, line, col);
-       }
-
-       void TagParsed (Tag tag, int line, int col)
-       {
-               if (waitClosing != null) {
-                       if (!(tag is CloseTag) || tag.TagID.ToUpper () != waitClosing.ToUpper ())
-                               throw new HttpException ("Tag " + waitClosing + " not properly closed.");
-
-                       waitClosing = null;
-                       controls.Pop ();
-                       return;
-               }
-               
-               if ((sstatus == ScriptStatus.Open || sstatus == ScriptStatus.Text) &&
-                    tag.TagID.ToUpper () == "SCRIPT" && tag is CloseTag) {
-                       sstatus = ScriptStatus.Close;
-                       return;
-               }
-
-               current = tag;
-
-               if (current is Directive) {
-                       ProcessDirective ();
-                       return;
-               } else if (current is DataBindingTag) {
-                       if (IsApplication)
-                               throw new ApplicationException (app_file_wrong);
-
-                       ProcessDataBindingLiteral ();
-                       return;
-               } else if (current is CodeRenderTag) {
-                       if (IsApplication)
-                               throw new ApplicationException (app_file_wrong);
-
-                       ProcessCodeRenderTag ();
-                       return;
-               }
-
-               current = Map (tag);
-
-               if (current is ServerObjectTag) {
-                       ProcessServerObjectTag ();
-                       return;
-               } else if (current is HtmlControlTag) {
-                       ProcessHtmlControlTag ();
-                       return;
-               }
-
-               if (IsApplication)
-                       throw new ApplicationException (app_file_wrong);
-
-               if (current is AspComponent) {
-                       ProcessComponent ();
-               } else if (current is CloseTag) {
-                       ProcessCloseTag ();
-               } else if (current is Tag) {
-                       ProcessHtmlTag ();
-               } else {
-                       throw new HttpException ("This place should not be reached.");
-               }
-       }
-
-       void TextParsed (string text, int line, int col)
-       {
-               if (sstatus == ScriptStatus.Open) {
-                       script.Append (text);
-                       sstatus = ScriptStatus.Text;
-                       return;
-               }
-
-               textChunk.Append (text);
-       }
-
-       public void ProcessElements ()
-       {
-               AspParser parser = new AspParser (fullPath, File.OpenRead (fullPath));
-               
-               parser.Error += new ParseErrorHandler (ParseError);
-               parser.TagParsed += new TagParsedHandler (TagParsed);
-               parser.TextParsed += new TextParsedHandler (TextParsed);
-
-               try {
-                       parser.Parse ();
-               } catch (CompilationException e) {
-                       throw;
-               } catch (ParseException e) {
-                       throw;
-               } catch (Exception e) {
-                       throw new ParseException (fullPath, e.Message, parser.Line, parser.Column, e);
-               }
-
-               End ();
-               parse_ok = true;
-       }
-       
-       private string GetTemplateDirectory ()
-       {
-               string templatePath = Path.GetDirectoryName (fullPath);
-               string appPath = Path.GetDirectoryName (HttpRuntime.AppDomainAppPath);
-
-               if (templatePath == appPath)
-                       return "/";
-
-               templatePath = templatePath.Substring (appPath.Length);
-               if (Path.DirectorySeparatorChar != '/')
-                       templatePath = templatePath.Replace (Path.DirectorySeparatorChar, '/');
-                       
-               return templatePath;
-       }
-
-       private void End ()
-       {
-               FlushPlainText ();
-
-               if (isPage) {
-                       if (sessionState == SessionState.Enabled || sessionState == SessionState.ReadOnly)
-                               AddInterface (typeof (System.Web.SessionState.IRequiresSessionState));
-
-                       if (sessionState == SessionState.ReadOnly)
-                               AddInterface (typeof (System.Web.SessionState.IReadOnlySessionState));
-               }
-               
-               classDecl = "\tpublic class " + className + " : " + parent + interfaces + " {\n"; 
-               prolog.Append ("\n" + classDecl);
-               declarations.Append ("\t\tprivate static bool __intialized = false;\n\n");
-               if (IsPage)
-                       declarations.Append ("\t\tprivate static ArrayList __fileDependencies;\n\n");
-
-               // adds the constructor
-               constructor.AppendFormat ("\t\tpublic {0} ()\n\t\t{{\n", className);
-               if (!IsApplication)
-                       constructor.Append ("\t\t\tSystem.Collections.ArrayList dependencies;\n\n");
-                       
-               constructor.AppendFormat ("\t\t\tif (ASP.{0}.__intialized == false){{\n", className); 
-
-               if (IsPage) {
-                       constructor.AppendFormat ("\t\t\t\tdependencies = new System.Collections.ArrayList ();\n" +
-                                               "\t\t\t\tdependencies.Add (@\"{1}\");\n" +
-                                               "\t\t\t\tASP.{0}.__fileDependencies = dependencies;\n",
-                                               className, fullPath);
-               }
-
-               constructor.AppendFormat ("\t\t\t\tASP.{0}.__intialized = true;\n\t\t\t}}\n\t\t}}\n\n",
-                                         className);
-         
-               if (!IsApplication) {
-                       //FIXME: add AutoHandlers: don't know what for...yet!
-                       constructor.AppendFormat (
-                               "\t\tprotected override int AutoHandlers\n\t\t{{\n" +
-                               "\t\t\tget {{ return ASP.{0}.__autoHandlers; }}\n" +
-                               "\t\t\tset {{ ASP.{0}.__autoHandlers = value; }}\n" +
-                               "\t\t}}\n\n", className);
-
-                       constructor.Append (
-                               "\t\tprotected System.Web.HttpApplication ApplicationInstance\n\t\t{\n" +
-                               "\t\t\tget { return (System.Web.HttpApplication) this.Context.ApplicationInstance; }\n" +
-                               "\t\t}\n\n");
-
-                       constructor.AppendFormat (
-                               "\t\tpublic override string TemplateSourceDirectory\n\t\t{{\n" +
-                               "\t\t\tget {{ return \"{0}\"; }}\n" +
-                               "\t\t}}\n\n", GetTemplateDirectory ());
-
-                       epilog.Append ("\n\t\tprotected override void FrameworkInitialize ()\n\t\t{\n" +
-                                       "\t\t\tthis.__BuildControlTree (this);\n");
-
-                       if (IsPage) {
-                               epilog.AppendFormat ("\t\t\tthis.FileDependencies = ASP.{0}.__fileDependencies;\n" +
-                                                       "\t\t\tthis.EnableViewStateMac = true;\n", className);
-                       }
-
-                       epilog.Append ("\t\t}\n\n");
-               }
-
-               if (IsPage) {
-                       Random rnd = new Random ();
-                       epilog.AppendFormat ("\t\tpublic override int GetTypeHashCode ()\n\t\t{{\n" +
-                                            "\t\t\treturn {0};\n" +
-                                            "\t\t}}\n", rnd.Next ());
-               }
-
-               epilog.Append ("\t}\n}\n");
-
-               // Closes the currently opened tags
-               StringBuilder old_function = current_function;
-               string control_id;
-               while (functions.Count > 1){
-                       old_function.Append ("\n\t\t\treturn __ctrl;\n\t\t}\n\n");
-                       init_funcs.Append (old_function);
-                       control_id = controls.PeekControlID ();
-                       FinishControlFunction (control_id);
-                       controls.AddChild ();
-                       old_function = (StringBuilder) functions.Pop ();
-                       current_function = (StringBuilder) functions.Peek ();
-                       controls.Pop ();
-               }
-
-               bool useCodeRender = controls.UseCodeRender;
-               if (useCodeRender){
-                       RemoveLiterals (current_function);
-                       AddRenderMethodDelegate (current_function, controls.PeekControlID ());
-               }
-               
-               current_function.Append ("\t\t}\n\n");
-               init_funcs.Append (current_function);
-               if (useCodeRender)
-                       AddCodeRenderFunction (controls.CodeRenderFunction.ToString (), controls.PeekControlID ());
-
-               functions.Pop ();
-       }
-
-       //
-       // Functions related to compilation of user controls
-       //
-       
-       private static char dirSeparator = Path.DirectorySeparatorChar;
-       struct UserControlData
-       {
-               public UserControlResult result;
-               public string className;
-               public string assemblyName;
        }
-
-       private UserControlData GenerateUserControl (string src, HttpContext context)
-       {
-               UserControlData data = new UserControlData ();
-               data.result = UserControlResult.OK;
-
-               UserControlCompiler compiler = new UserControlCompiler (new UserControlParser (src, context));
-               Type t = compiler.GetCompiledType ();
-               if (t == null) {
-                       data.result = UserControlResult.CompilationFailed;
-                       return data;
-               }
-               
-               data.className = t.Name;
-               data.assemblyName = compiler.TargetFile;
-               dependencies.Add (src);
-               foreach (string s in compiler.Dependencies)
-                       dependencies.Add (s);
-               
-               return data;
-       }
-}
-
 }
 
index 06867ac354d21f1a7da0d275da526672ab616bfb..05f62357aefa29cb75c17669211580a234ab7858 100644 (file)
@@ -4,7 +4,7 @@
 // Authors:
 //     Gonzalo Paniagua Javier (gonzalo@ximian.com)
 //
-// (C) 2002 Ximian, Inc (http://www.ximian.com)
+// (C) 2002,2003 Ximian, Inc (http://www.ximian.com)
 //
 using System;
 using System.Collections;
@@ -13,109 +13,166 @@ using System.Text;
 
 namespace System.Web.Compilation
 {
-       delegate void ParseErrorHandler (string msg, int line, int col);
-       delegate void TagParsedHandler (Tag tag, int line, int col);
-       delegate void TextParsedHandler (string text, int line, int col);
+       delegate void ParseErrorHandler (ILocation location, string message);
+       delegate void TextParsedHandler (ILocation location, string text);
+       delegate void TagParsedHandler (ILocation location, TagType tagtype, string id, TagAttributes attributes);
+
+       class AspParser : ILocation
+       {
+               AspTokenizer tokenizer;
+               int beginLine, endLine;
+               int beginColumn, endColumn;
+               int beginPosition, endPosition;
+               string filename;
+               string fileText;
+               string verbatimID;
+
+               public AspParser (string filename, StreamReader input)
+               {
+                       this.filename = filename;
+                       fileText = input.ReadToEnd ();
+                       StringReader reader = new StringReader (fileText);
+                       tokenizer = new AspTokenizer (reader);
+               }
 
-       class AspParser {
-               private AspTokenizer tokenizer;
+               public int BeginLine {
+                       get { return beginLine; }
+               }
 
-               public AspParser (AspTokenizer tokenizer)
-               {
-                       this.tokenizer = tokenizer;
+               public int BeginColumn {
+                       get { return beginColumn; }
                }
 
-               public AspParser (string filename, Stream input) : 
-                       this (new AspTokenizer (filename, input))
-               {
+               public int EndLine {
+                       get { return endLine; }
                }
 
-               public int Line {
-                       get {return tokenizer.Line; }
+               public int EndColumn {
+                       get { return endColumn; }
                }
 
-               public int Column {
-                       get {return tokenizer.Column; }
+               public string PlainText {
+                       get {
+                               if (beginPosition >= endPosition)
+                                       return null;
+
+                               return fileText.Substring (beginPosition, endPosition - beginPosition);
+                       }
                }
 
-               private bool Eat (int expected_token)
+               public string Filename {
+                       get { return filename; }
+               }
+
+               public string VerbatimID {
+                       set {
+                               tokenizer.Verbatim = true;
+                               verbatimID = value.ToUpper ();
+                       }
+               }
+               
+               bool Eat (int expected_token)
                {
                        if (tokenizer.get_token () != expected_token) {
                                tokenizer.put_back ();
                                return false;
                        }
+
+                       endLine = tokenizer.EndLine;
+                       endColumn = tokenizer.EndColumn;
                        return true;
                }
 
+               void BeginElement ()
+               {
+                       beginLine = tokenizer.BeginLine;
+                       beginColumn = tokenizer.BeginColumn;
+                       beginPosition = tokenizer.Position - 1;
+               }
+
+               void EndElement ()
+               {
+                       endLine = tokenizer.EndLine;
+                       endColumn = tokenizer.EndColumn;
+                       endPosition = tokenizer.Position;
+               }
+
                public void Parse ()
                {
                        int token;
-                       Element element;
-                       Tag tag_element;
-                       string tag = "";
+                       string id;
+                       TagAttributes attributes;
+                       TagType tagtype;
+                       StringBuilder text =  new StringBuilder ();
+
+                       while ((token = tokenizer.get_token ()) != Token.EOF) {
+                               BeginElement ();
 
-                       while ((token = tokenizer.get_token ()) != Token.EOF){
                                if (tokenizer.Verbatim){
-                                       string end_verbatim = "</" + tag + ">";
+                                       string end_verbatim = "</" + verbatimID + ">";
                                        string verbatim_text = GetVerbatim (token, end_verbatim);
 
                                        if (verbatim_text == null)
-                                               OnError ("Unexpected EOF processing " + tag);
+                                               OnError ("Unexpected EOF processing " + verbatimID);
 
-                                       OnTextParsed (verbatim_text);
-                                       OnTagParsed (new CloseTag (tag));
                                        tokenizer.Verbatim = false;
-                               }
-                               else if (token == '<') {
-                                       element = GetTag ();
-                                       if (element == null)
-                                               OnError ("");
 
-                                       if (element is ServerComment)
-                                               continue;
-
-                                       if (!(element is Tag)){
-                                               OnTextParsed (((PlainText) element).Text);
+                                       EndElement ();
+                                       endPosition -= end_verbatim.Length;
+                                       OnTextParsed (verbatim_text);
+                                       beginPosition = endPosition;
+                                       endPosition += end_verbatim.Length;
+                                       OnTagParsed (TagType.Close, verbatimID, null);
+                                       continue;
+                               }
+                               
+                               if (token == '<') {
+                                       GetTag (out tagtype, out id, out attributes);
+                                       EndElement ();
+                                       if (tagtype == TagType.ServerComment)
                                                continue;
-                                       }
 
-                                       OnTagParsed ((Tag) element);
+                                       if (tagtype == TagType.Text)
+                                               OnTextParsed (id);
+                                       else
+                                               OnTagParsed (tagtype, id, attributes);
 
-                                       tag_element = (Tag) element;
-                                       //FIXME: move this to the TagParsed handler.
-                                       tag = tag_element.TagID.ToUpper ();
-                                       if (!tag_element.SelfClosing && (tag == "SCRIPT" || tag == "PRE"))
-                                               tokenizer.Verbatim = true;
-                               }
-                               else {
-                                       StringBuilder text =  new StringBuilder ();
-                                       do {
-                                               text.Append (tokenizer.value);
-                                               token = tokenizer.get_token ();
-                                       } while (token != '<' && token != Token.EOF);
-                                       tokenizer.put_back ();
-                                       OnTextParsed (text.ToString ());
+                                       continue;
                                }
+
+                               text.Length = 0;
+                               do {
+                                       text.Append (tokenizer.Value);
+                                       token = tokenizer.get_token ();
+                               } while (token != '<' && token != Token.EOF);
+
+                               tokenizer.put_back ();
+                               EndElement ();
+                               OnTextParsed (text.ToString ());
                        }
                }
 
-               private Element GetTag ()
+               void GetTag (out TagType tagtype, out string id, out TagAttributes attributes)
                {
                        int token = tokenizer.get_token ();
-                       string id;
 
+                       tagtype = TagType.ServerComment;
+                       id = null;
+                       attributes = null;
                        switch (token){
                        case '%':
-                               return GetServerTag ();
+                               GetServerTag (out tagtype, out id, out attributes);
+                               break;
                        case '/':
                                if (!Eat (Token.IDENTIFIER))
                                        OnError ("expecting TAGNAME");
 
-                               id = tokenizer.value;
+                               id = tokenizer.Value;
                                if (!Eat ('>'))
                                        OnError ("expecting '>'");
 
-                               return new CloseTag (id);
+                               tagtype = TagType.Close;
+                               break;
                        case '!':
                                bool double_dash = Eat (Token.DOUBLEDASH);
                                if (double_dash)
@@ -128,19 +185,27 @@ namespace System.Web.Compilation
                                if (comment == null)
                                        OnError ("Unfinished HTML comment/DTD");
 
-                               return new PlainText ("<!" + comment + end);
+                               tagtype = TagType.Text;
+                               id = "<!" + comment + end;
+                               break;
                        case Token.IDENTIFIER:
-                               id = tokenizer.value;
-                               Tag tag = new Tag (id, GetAttributes (), Eat ('/'));
-                               if (!Eat ('>'))
+                               id = tokenizer.Value;
+                               attributes = GetAttributes ();
+                               tagtype = TagType.Tag;
+                               if (Eat ('/') && Eat ('>'))
+                                       tagtype = TagType.SelfClosing;
+                               else if (!Eat ('>'))
                                        OnError ("expecting '>'");
-                               return tag;
+
+                               break;
                        default:
-                               return new PlainText ("<" + tokenizer.value);
+                               tagtype = TagType.Text;
+                               id = "<" + tokenizer.Value;
+                               break;
                        }
                }
 
-               private TagAttributes GetAttributes ()
+               TagAttributes GetAttributes ()
                {
                        int token;
                        TagAttributes attributes;
@@ -150,10 +215,10 @@ namespace System.Web.Compilation
                        while ((token = tokenizer.get_token ())  != Token.EOF){
                                if (token != Token.IDENTIFIER)
                                        break;
-                               id = tokenizer.value;
+                               id = tokenizer.Value;
                                if (Eat ('=')){
                                        if (Eat (Token.ATTVALUE)){
-                                               attributes.Add (id, tokenizer.value);
+                                               attributes.Add (id, tokenizer.Value);
                                        } else {
                                                //TODO: support data binding syntax without quotes
                                                OnError ("expected ATTVALUE");
@@ -172,14 +237,14 @@ namespace System.Web.Compilation
                        return attributes;
                }
 
-               private string GetVerbatim (int token, string end)
+               string GetVerbatim (int token, string end)
                {
                        StringBuilder vb_text = new StringBuilder ();
                        int i = 0;
 
-                       if (tokenizer.value.Length > 1){
+                       if (tokenizer.Value.Length > 1){
                                // May be we have a put_back token that is not a single character
-                               vb_text.Append (tokenizer.value);
+                               vb_text.Append (tokenizer.Value);
                                token = tokenizer.get_token ();
                        }
 
@@ -189,24 +254,20 @@ namespace System.Web.Compilation
                                                break;
                                        token = tokenizer.get_token ();
                                        continue;
-                               }
-                               else {
+                               } else if (i > 0) {
                                        for (int j = 0; j < i; j++)
                                                vb_text.Append (end [j]);
+                                       i = 0;
                                }
 
-                               i = 0;
                                vb_text.Append ((char) token);
                                token = tokenizer.get_token ();
                        } 
 
-                       if (token == Token.EOF)
-                               return null;
-
                        return RemoveComments (vb_text.ToString ());
                }
 
-               private string RemoveComments (string text)
+               string RemoveComments (string text)
                {
                        int end;
                        int start = text.IndexOf ("<%--");
@@ -223,24 +284,31 @@ namespace System.Web.Compilation
                        return text;
                }
 
-               private Element GetServerTag ()
+               void GetServerTag (out TagType tagtype, out string id, out TagAttributes attributes)
                {
-                       string id;
                        string inside_tags;
-                       TagAttributes attributes;
 
                        if (Eat ('@')){
-                               id = (Eat (Token.DIRECTIVE) ? tokenizer.value : "Page");
+                               tagtype = TagType.Directive;
+                               id = "";
+                               if (Eat (Token.DIRECTIVE))
+                                       id = tokenizer.Value;
+
                                attributes = GetAttributes ();
                                if (!Eat ('%') || !Eat ('>'))
                                        OnError ("expecting '%>'");
 
-                               return new Directive (id, attributes);
-                       } else if (Eat (Token.DOUBLEDASH)) {
+                               return;
+                       }
+                       
+                       if (Eat (Token.DOUBLEDASH)) {
                                tokenizer.Verbatim = true;
                                inside_tags = GetVerbatim (tokenizer.get_token (), "--%>");
                                tokenizer.Verbatim = false;
-                               return new ServerComment ("<%--" + inside_tags + "--%>");
+                               id = null;
+                               attributes = null;
+                               tagtype = TagType.ServerComment;
+                               return;
                        }
 
                        bool varname;
@@ -251,10 +319,10 @@ namespace System.Web.Compilation
                        tokenizer.Verbatim = true;
                        inside_tags = GetVerbatim (tokenizer.get_token (), "%>");
                        tokenizer.Verbatim = false;
-                       if (databinding)
-                               return new DataBindingTag (inside_tags);
-
-                       return new CodeRenderTag (varname, inside_tags);
+                       id = inside_tags;
+                       attributes = null;
+                       tagtype = (databinding ? TagType.DataBinding :
+                                 (varname ? TagType.CodeRenderExpression : TagType.CodeRender));
                }
 
                public event ParseErrorHandler Error;
@@ -264,19 +332,19 @@ namespace System.Web.Compilation
                void OnError (string msg)
                {
                        if (Error != null)
-                               Error (msg, tokenizer.Line, tokenizer.Column);
+                               Error (this, msg);
                }
 
-               void OnTagParsed (Tag tag)
+               void OnTagParsed (TagType tagtype, string id, TagAttributes attributes)
                {
                        if (TagParsed != null)
-                               TagParsed (tag, tokenizer.Line, tokenizer.Column);
+                               TagParsed (this, tagtype, id, attributes);
                }
 
                void OnTextParsed (string text)
                {
                        if (TextParsed != null)
-                               TextParsed (text, tokenizer.Line, tokenizer.Column);
+                               TextParsed (this, text);
                }
        }
 
index 3e6bacb6ab3026ecd7bcfb14e543f0146992f13c..b51d7d985c3077b93000adfb3395073388a93329 100644 (file)
@@ -4,7 +4,7 @@
 // Authors:
 //     Gonzalo Paniagua Javier (gonzalo@ximian.com)
 //
-// (C) 2002 Ximian, Inc (http://www.ximian.com)
+// (C) 2002,2003 Ximian, Inc (http://www.ximian.com)
 //
 
 using System;
@@ -12,36 +12,36 @@ using System.Collections;
 using System.IO;
 using System.Text;
 
-namespace System.Web.Compilation {
-       
+namespace System.Web.Compilation
+{
        class Token
        {
                public const int EOF            = 0;
                public const int IDENTIFIER     = 1000;
-               public const int DIRECTIVE      = 1001;
+               public const int DIRECTIVE      = 1001;
                public const int ATTVALUE       = 1002;
                public const int TEXT           = 1003;
                public const int DOUBLEDASH     = 1004;
                public const int CLOSING        = 1005;
        }
 
-       class AspTokenizer {
-               private StreamReader sr;
-               private int current_token;
-               private StringBuilder sb;
-               private int col, line;
-               private bool inTag;
-               private bool hasPutBack;
-               private bool verbatim;
-               private string filename;
+       class AspTokenizer
+       {
+               TextReader sr;
+               int current_token;
+               StringBuilder sb;
+               int col, line;
+               int begcol, begline;
+               int position;
+               bool inTag;
+               bool hasPutBack;
+               bool verbatim;
+               bool have_value;
+               string val;
                
-               public AspTokenizer (string filename, Stream stream)
+               public AspTokenizer (TextReader reader)
                {
-                       if (filename == null || stream == null)
-                               throw new ArgumentNullException ();
-
-                       this.sr = new StreamReader (stream);
-                       this.filename = filename;
+                       this.sr = reader;
                        sb = new StringBuilder ();
                        col = line = 1;
                        hasPutBack = inTag = false;
@@ -56,18 +56,23 @@ namespace System.Web.Compilation {
                public void put_back ()
                {
                        if (hasPutBack)
-                               throw new ApplicationException ("put_back called twice!");
-                               
+                               throw new HttpException ("put_back called twice!");
+                       
                        hasPutBack = true;
+                       position -= Value.Length;
                }
                
                public int get_token ()
                {
                        if (hasPutBack){
                                hasPutBack = false;
+                               position += Value.Length;
                                return current_token;
                        }
 
+                       begline = line;
+                       begcol = col;
+                       have_value = false;
                        current_token = NextToken ();
                        return current_token;
                }
@@ -82,24 +87,29 @@ namespace System.Web.Compilation {
                        return (Char.IsLetterOrDigit (c) || c == '_' || c == '-');
                }
 
-               private int read_char ()
+               int read_char ()
                {
                        int c = sr.Read ();
 
-                       if (c == '\r' && sr.Peek () == '\n')
+                       if (c == '\r' && sr.Peek () == '\n') {
                                c = sr.Read ();
+                               position++;
+                       }
 
                        if (c == '\n'){
-                               col = 0;
+                               col = -1;
                                line++;
                        }
-                       else if (c != -1)
+
+                       if (c != -1) {
                                col++;
+                               position++;
+                       }
 
                        return c;
                }
 
-               private int ReadAttValue (int start)
+               int ReadAttValue (int start)
                {
                        int quoteChar = 0;
                        bool quoted = false;
@@ -137,7 +147,7 @@ namespace System.Web.Compilation {
                        return Token.ATTVALUE;
                }
 
-               private int NextToken ()
+               int NextToken ()
                {
                        int c;
                        
@@ -199,9 +209,9 @@ namespace System.Web.Compilation {
                                                sb.Append ((char) read_char ());
                                        }
 
-                                       if (current_token == '@' && Directive.IsDirectiveID (sb.ToString ()))
+                                       if (current_token == '@' && Directive.IsDirective (sb.ToString ()))
                                                return Token.DIRECTIVE;
-
+                                       
                                        return Token.IDENTIFIER;
                                }
 
@@ -212,30 +222,36 @@ namespace System.Web.Compilation {
                        return Token.EOF;
                }
 
-               public string value {
-                       get { return sb.ToString (); }
-               }
-
-               public int Line {
+               public string Value {
                        get {
-                               return line;
+                               if (have_value)
+                                       return val;
+
+                               have_value = true;
+                               val = sb.ToString ();
+                               return val;
                        }
                }
 
-               public int Column {
-                       get {
-                               return col;
-                       }
+               public int BeginLine {
+                       get { return begline; }
                }
 
-               public string Location {
-                       get { 
-                               string msg = filename;
-                               msg += " (" + line + ", " + col + "): " + sb.ToString ();
-                               return msg;
-                       }
+               public int BeginColumn {
+                       get { return begcol; }
                }
 
+               public int EndLine {
+                       get { return line; }
+               }
+
+               public int EndColumn {
+                       get { return col; }
+               }
+
+               public int Position {
+                       get { return position; }
+               }
        }
 }
 
index 28699ca366f4c04e45f3428a93d21556946cb699..12ce26cbbefd8fb68978b8412e5738077e6677b3 100644 (file)
 // Authors:
 //     Gonzalo Paniagua Javier (gonzalo@ximian.com)
 //
-// (C) 2002 Ximian, Inc (http://www.ximian.com)
+// (C) 2002,2003 Ximian, Inc (http://www.ximian.com)
 //
 
 using System;
+using System.CodeDom;
+using System.CodeDom.Compiler;
 using System.Collections;
-using System.IO;
+using System.Reflection;
 using System.Text;
+using System.Web.UI;
+//temp:
+using Microsoft.CSharp;
+using System.IO;
 
 namespace System.Web.Compilation
 {
        abstract class BaseCompiler
        {
-               //FIXME: configurable?
-               static string default_assemblies = "System.Web.dll, System.Data.dll, System.Drawing.dll";
-               static Random rnd = new Random ((int) DateTime.Now.Ticks);
-               string randomName;
-               protected Hashtable options;
-               protected ArrayList dependencies;
-
-               protected BaseCompiler ()
+               TemplateParser parser;
+               CodeDomProvider provider;
+               ICodeCompiler compiler;
+               CodeCompileUnit unit;
+               CodeNamespace mainNS;
+               CompilerParameters compilerParameters;
+               protected CodeTypeDeclaration mainClass;
+               protected CodeTypeReferenceExpression mainClassExpr;
+               protected static CodeThisReferenceExpression thisRef = new CodeThisReferenceExpression ();
+
+               protected BaseCompiler (TemplateParser parser)
                {
+                       compilerParameters = new CompilerParameters ();
+                       this.parser = parser;
                }
 
-               public virtual Type GetCompiledType ()
+               void Init ()
                {
-                       return null;
-               }
+                       unit = new CodeCompileUnit ();
+                       mainNS = new CodeNamespace ("ASP");
+                       unit.Namespaces.Add (mainNS);
+                       mainClass = new CodeTypeDeclaration (parser.ClassName);
+                       mainClass.TypeAttributes = TypeAttributes.Public;
+                       mainNS.Types.Add (mainClass);
+                       mainClass.BaseTypes.Add (new CodeTypeReference (parser.BaseType.FullName));
+                       mainClassExpr = new CodeTypeReferenceExpression ("ASP." + parser.ClassName);
+                       foreach (object o in parser.Imports) {
+                               if (o is string)
+                                       mainNS.Imports.Add (new CodeNamespaceImport ((string) o));
+                       }
 
-               public virtual string Key {
-                       get {
-                               return null;
+                       if (parser.Assemblies != null) {
+                               foreach (object o in parser.Assemblies) {
+                                       if (o is string)
+                                               unit.ReferencedAssemblies.Add ((string) o);
+                               }
                        }
+
+                       AddInterfaces ();
+                       CreateStaticFields ();
+                       AddScripts ();
+                       CreateConstructor (null, null);
                }
 
-               public virtual string SourceFile {
-                       get {
-                               return null;
-                       }
+               void BuildTree ()
+               {
+                       Init ();
+                       CreateMethods ();
                }
 
-               public virtual string [] Dependencies {
-                       get {
-                               if (dependencies == null)
-                                       return new string [0];
+               protected virtual void CreateStaticFields ()
+               {
+                       CodeMemberField fld = new CodeMemberField (typeof (bool), "__intialized");
+                       fld.Attributes = MemberAttributes.Private | MemberAttributes.Static;
+                       fld.InitExpression = new CodePrimitiveExpression (false);
+                       mainClass.Members.Add (fld);
+               }
 
-                               return (string []) dependencies.ToArray (typeof (string));
+               protected virtual void CreateConstructor (CodeStatementCollection localVars, CodeStatementCollection trueStmt)
+               {
+                       CodeConstructor ctor = new CodeConstructor ();
+                       ctor.Attributes = MemberAttributes.Public;
+                       mainClass.Members.Add (ctor);
+
+                       if (localVars != null)
+                               ctor.Statements.AddRange (localVars);
+
+                       CodeTypeReferenceExpression r = new CodeTypeReferenceExpression (mainNS.Name + "." + mainClass.Name);
+                       CodeFieldReferenceExpression intialized = new CodeFieldReferenceExpression (r, "__intialized");
+                       
+                       CodeBinaryOperatorExpression bin = new CodeBinaryOperatorExpression (intialized,
+                                                                                            CodeBinaryOperatorType.ValueEquality,
+                                                                                            new CodePrimitiveExpression (false));
+
+                       CodeAssignStatement assign = new CodeAssignStatement (intialized,
+                                                                             new CodePrimitiveExpression (true));
+
+                       CodeConditionStatement cond = new CodeConditionStatement (bin, assign);
+                       if (trueStmt != null)
+                               cond.TrueStatements.AddRange (trueStmt);
+                       
+                       ctor.Statements.Add (cond);
+               }
+               
+               void AddScripts ()
+               {
+                       if (parser.Scripts == null || parser.Scripts.Count == 0)
+                               return;
+
+                       foreach (object o in parser.Scripts) {
+                               if (o is string)
+                                       mainClass.Members.Add (new CodeSnippetTypeMember ((string) o));
                        }
                }
+               
+               protected virtual void CreateMethods ()
+               {
+               }
 
-               public virtual void AddDependency (string filename)
+               protected virtual void AddInterfaces ()
                {
-                       if (dependencies == null)
-                               dependencies = new ArrayList ();
+                       if (parser.Interfaces == null)
+                               return;
 
-                       dependencies.Add (filename);
+                       foreach (object o in parser.Interfaces) {
+                               if (o is string)
+                                       mainClass.BaseTypes.Add (new CodeTypeReference ((string) o));
+                       }
                }
-               
-               public virtual string CompilerOptions {
-                       get {
-                               string assemblies = default_assemblies;
-                               string privatePath = AppDomain.CurrentDomain.SetupInformation.PrivateBinPath;
-                               string appBase = AppDomain.CurrentDomain.SetupInformation.ApplicationBase;
-                               //HACK: we should use Uri (appBase).LocalPath once Uri works fine.
-                               if (appBase.StartsWith ("file://")) {
-                                       appBase = appBase.Substring (7);
-                                       if (Path.DirectorySeparatorChar == '\\')
-                                               appBase = appBase.Replace ('/', '\\');
-                               }
 
-                               privatePath = Path.Combine (appBase, privatePath);
+               protected virtual void ProcessObjectTag (ObjectTagBuilder tag)
+               {
+               }
 
-                               if (privatePath != null && Directory.Exists (privatePath)) {
-                                       StringBuilder sb = new StringBuilder (assemblies);
-                                       foreach (string fileName in Directory.GetFiles (privatePath, "*.dll"))
-                                               sb.AppendFormat (", {0}", fileName);
-                                       assemblies = sb.ToString ();
-                                       sb = null;
-                               }
+               void CheckCompilerErrors (CompilerResults results)
+               {
+                       if (results.NativeCompilerReturnValue == 0)
+                               return;
+                       StringWriter writer = new StringWriter();
+                       provider.CreateGenerator().GenerateCodeFromCompileUnit (unit, writer, null);
+                       StringBuilder sb = new StringBuilder ();
+                       foreach (CompilerError error in results.Errors) {
+                               sb.Append (error);
+                               sb.Append ('\n');
+                       }
 
-                               string [] split = assemblies.Split (',');
-                               StringBuilder result = new StringBuilder ();
-                               foreach (string assembly in split)
-                                       result.AppendFormat ("/r:\"{0}\" ", assembly.TrimStart ());
-                               
-                               if (options == null)
-                                       return result.ToString ();
-
-                               string compilerOptions = options ["CompilerOptions"] as string;
-                               if (compilerOptions != null) {
-                                       result.Append (' ');
-                                       result.Append (compilerOptions);
-                               }
+                       throw new CompilationException (parser.InputFile, sb.ToString (), writer.ToString ());
+               }
 
-                               string references = options ["References"] as string;
-                               if (references == null)
-                                       return result.ToString ();
+               public virtual Type GetCompiledType () 
+               {
+                       //TODO: get the compiler and default options from system.web/compileroptions
+                       provider = new CSharpCodeProvider ();
+                       compiler = provider.CreateCompiler ();
 
-                               split = references.Split ('|');
-                               foreach (string s in split)
-                                       result.AppendFormat (" /r:\"{0}\"", s);
+                       BuildTree ();
+                       CompilerResults results = CachingCompiler.Compile (this);
+                       CheckCompilerErrors (results);
 
-                               return result.ToString ();
-                       }
+                       return results.CompiledAssembly.GetType (mainClassExpr.Type.BaseType, true);
                }
 
-               public virtual string TargetFile {
-                       get {
-                               if (randomName == null) {
-                                       randomName = Path.GetTempFileName ();
-                                       try {
-                                               File.Delete (randomName);
-                                       } catch {}
-                                       randomName += ".dll";
-                               }
+               internal CompilerParameters CompilerParameters {
+                       get { return compilerParameters; }
+               }
 
-                               return randomName;
-                       }
+               internal CodeCompileUnit Unit {
+                       get { return unit; }
+               }
+
+               internal ICodeCompiler Compiler {
+                       get { return compiler; }
+               }
+
+               internal TemplateParser Parser {
+                       get { return parser; }
                }
        }
 }
diff --git a/mcs/class/System.Web/System.Web.Compilation/CSCompiler.cs b/mcs/class/System.Web/System.Web.Compilation/CSCompiler.cs
new file mode 100644 (file)
index 0000000..035692a
--- /dev/null
@@ -0,0 +1,77 @@
+//
+// System.Web.Compilation.CSCompiler
+//
+// Authors:
+//     Gonzalo Paniagua Javier (gonzalo@ximian.com)
+//
+// (C) 2003 Ximian, Inc (http://www.ximian.com)
+//
+using System;
+using System.CodeDom;
+using System.CodeDom.Compiler;
+using System.Collections;
+using System.Collections.Specialized;
+using System.Text;
+using System.Reflection;
+using Microsoft.CSharp;
+
+namespace System.Web.Compilation
+{
+       class CSCompiler
+       {
+               static CodeDomProvider provider;
+               static ICodeCompiler compiler;
+               string filename;
+               ArrayList assemblies;
+               CompilerParameters options;
+
+               static CSCompiler ()
+               {
+                       provider = new CSharpCodeProvider ();
+                       compiler = provider.CreateCompiler ();
+               }
+
+               private CSCompiler (string filename, ArrayList assemblies)
+               {
+                       this.filename = filename;
+                       this.assemblies = assemblies;
+                       options = new CompilerParameters ();
+                       if (assemblies != null) {
+                               StringCollection coll = new StringCollection ();
+                               foreach (string str in assemblies)
+                                       coll.Add (str);
+                       }
+               }
+
+               public Assembly GetCompiledAssembly ()
+               {
+                       CompilerResults results = compiler.CompileAssemblyFromFile (options, filename);
+                       if (results.NativeCompilerReturnValue != 0) {
+                               StringBuilder errors = new StringBuilder ();
+                               foreach (CompilerError error in results.Errors) {
+                                       errors.Append (error);
+                                       errors.Append ('\n');
+                               }
+
+                               throw new HttpException ("Error compiling " + filename + "\n" + errors.ToString ());
+                       }
+
+                       return results.CompiledAssembly;
+               }
+
+               static public Assembly CompileCSFile (string file, ArrayList assemblies)
+               {
+                       CSCompiler compiler = new CSCompiler (file, assemblies);
+                       return compiler.GetCompiledAssembly ();
+               }
+
+               static public CodeDomProvider Provider {
+                       get { return provider; }
+               }
+
+               static public ICodeCompiler Compiler {
+                       get { return compiler; }
+               }
+       }
+}
+
index 8f714af51e7c5fef3933b5141f443980f9985d2f..3d23bb0a3561a4e09193b57db2df0bd83e8a4b53 100644 (file)
@@ -7,52 +7,42 @@
 // (C) 2002 Ximian, Inc (http://www.ximian.com)
 //
 using System;
+using System.CodeDom;
+using System.CodeDom.Compiler;
 using System.Collections;
-using System.Diagnostics;
 using System.IO;
-using System.Text;
 using System.Web.UI;
-using System.Web.Util;
 
 namespace System.Web.Compilation
 {
        //TODO: caching should be done using System.Web.Caching, but that namespace still need some work.
        internal class CompilationCacheItem
        {
-               CompilationResult result;
+               CompilerResults result;
+               ArrayList dependencies;
                DateTime reference;
-               bool invalidated;
 
-               public CompilationCacheItem (CompilationResult result)
+               public CompilationCacheItem (CompilerResults result, ArrayList dependencies)
                {
                        this.result = result;
-                       try {
-                               this.reference = File.GetLastWriteTime (result.OutputFile);
-                       } catch (FileNotFoundException){
-                               this.reference = DateTime.Now;
-                       }
+                       this.dependencies = dependencies;
+                       this.reference = DateTime.Now;
                }
 
-               public bool CheckDependencies ()
+               public bool CheckDependencies (string key)
                {
-                       if (invalidated || result.Dependencies == null)
-                               return false;
-
-                       if (!File.Exists (result.OutputFile))
-                               return false;
+                       if (dependencies == null)
+                               return true; // Forever young
 
-                       foreach (string s in result.Dependencies) {
-                               if (!File.Exists (s) || File.GetLastWriteTime (s) > reference) {
-                                       invalidated = true;
+                       foreach (string s in dependencies) {
+                               if (!File.Exists (s) || File.GetLastWriteTime (s) > reference)
                                        return false;
-                               }
                        }
                        
                        return true;
                }
 
-               public CompilationResult Result
-               {
+               public CompilerResults Result {
                        get { return result; }
                }
        }
@@ -76,29 +66,26 @@ namespace System.Web.Compilation
                        return instance;
                }
 
-               public CompilationCacheItem this [string key]
+               public bool CheckDependencies (CompilationCacheItem item, string key)
                {
-                       get {
-                               return cache [key] as CompilationCacheItem;
-                       }
+                       bool result = item.CheckDependencies (key);
+                       if (result == false)
+                               cache.Remove (key);
 
-                       set {
-                               cache [key] = value;
-                       }
+                       return result;
+               }
+
+               public CompilationCacheItem this [string key] {
+                       get { return cache [key] as CompilationCacheItem; }
+                       set { cache [key] = value; }
                }
        }
        
        internal class CachingCompiler
        {
                static CompilationCache cache = CompilationCache.GetInstance ();
-               string key;
-               BaseCompiler compiler;
 
-               public CachingCompiler (BaseCompiler compiler)
-               {
-                       this.compiler = compiler;
-                       this.key = compiler.Key;
-               }
+               private CachingCompiler () {}
 
                public static CompilationCacheItem GetCached (string key)
                {
@@ -106,82 +93,31 @@ namespace System.Web.Compilation
                                throw new ArgumentNullException ("key");
 
                        CompilationCacheItem item = cache [key];
-                       if (item != null && item.CheckDependencies ())
+                       if (item != null && cache.CheckDependencies (item, key))
                                return item;
 
                        return null;
                }
 
                static object compilationLock = new object ();
-               public bool Compile (CompilationResult result)
+               public static CompilerResults Compile (BaseCompiler compiler)
                {
-                       if (compiler.SourceFile == null)
-                               throw new ArgumentException ("No source to compile!");
-
-                       result.Reset ();
-                       CompilationCacheItem item;
-
-                       item = GetCached (key);
-                       if (item != null) {
-                               result.CopyFrom (item.Result);
-                               return true;
-                       }
+                       string key = compiler.Parser.InputFile;
+                       CompilationCacheItem item = GetCached (key);
+                       if (item != null)
+                               return item.Result;
                        
+                       CompilerResults results = null;
                        lock (compilationLock) {
                                item = GetCached (key);
-                               if (item != null) {
-                                       result.CopyFrom (item.Result);
-                                       return true;
-                               }
+                               if (item != null)
+                                       return item.Result;
 
-                               RealCompile (result);
-                               cache [key] = new CompilationCacheItem (result);
+                               results = compiler.Compiler.CompileAssemblyFromDom (compiler.CompilerParameters, compiler.Unit);
+                               cache [key] = new CompilationCacheItem (results, compiler.Parser.Dependencies);
                        }
 
-                       return (result.ExitCode == 0);
-               }
-
-               void RealCompile (CompilationResult result)
-               {
-                       StringBuilder options = new StringBuilder ("/target:library ");
-                       if (compiler.CompilerOptions != null)
-                               options.Append (compiler.CompilerOptions + ' ');
-
-                       options.AppendFormat ("/out:\"{0}\" ", compiler.TargetFile);
-                       options.Append ('"' + compiler.SourceFile + '"');
-
-                       //Console.WriteLine ("mcs {0}", options);
-                       Process proc = new Process ();
-                       if (Path.DirectorySeparatorChar == '\\')
-                               proc.StartInfo.FileName = "mcs.bat";
-                       else
-                               proc.StartInfo.FileName = "mcs";
-
-                       proc.StartInfo.Arguments = options.ToString ();
-                       proc.StartInfo.UseShellExecute = false;
-                       proc.StartInfo.RedirectStandardOutput = true;
-
-                       WebTrace.WriteLine ("{0} {1}", proc.StartInfo.FileName, options.ToString ());
-                       try {
-                               proc.Start ();
-                       } catch (Exception e) {
-                               if (Path.DirectorySeparatorChar == '\\') {
-                                       proc.StartInfo.FileName = "mcs";
-                                       proc.Start ();
-                               } else {
-                                       throw e;
-                               }
-                       }
-
-                       string poutput = proc.StandardOutput.ReadToEnd();
-                       proc.WaitForExit ();
-                       result.ExitCode = proc.ExitCode;
-                       proc.Close ();
-                       proc = null;
-
-                       result.CompilerOutput = poutput;
-                       //Console.WriteLine ("output: {0}\n", poutput);
-                       result.OutputFile = compiler.TargetFile;
+                       return results;
                }
        }
 }
index 810a75c7bacedd71d5a8e7c1c65f8ec0e7b5dd70..1f08e42f2c66a879ba6a3ded2e2d1abae6be4cf2 100644 (file)
@@ -1,3 +1,59 @@
+2003-04-30  Gonzalo Paniagua Javier <gonzalo@ximian.com>
+
+       * AspComponentFoundry.cs: simplified it a lot by using Type and Assembly
+       instead of their names.
+
+       * AspElements.cs: removed. No longer needed.
+
+       * AspGenerator.cs: this file is now in charge of interfacing between
+       the parser and the compiler. It manages the creation of the
+       ControlBuilder tree and the compilation of the CodeDOM tree.
+
+       * AspParser.cs: tag handling is simpler now.  Instead of a whole bunch
+       of different Types, tags are just and id and a set of attributes.
+       Implement ILocation interface.
+       
+       * AspTokenizer.cs: added a few methods to help the parser implementing
+       ILocation.
+
+       * BaseCompiler.cs: handles the portions of the CodeDOM tree that are
+       common to appliaction, page and user control, including the actual
+       compilation and error handling.
+
+       * CSCompiler.cs: compiles C# files using CodeDOM interfaces.
+
+       * CachingCompiler.cs: simplified to use the new interfaces.
+
+       * CompilationException.cs: it's now using CompilationResult to report
+       errors.
+
+       * CompilationResult.cs: Removed file.
+
+       * Directive.cs: to check for the validity of a directive.
+
+       * GlobalAsaxCompiler.cs: simplified a lot, as most of the work is done
+       in BaseCompiler.
+
+       * ILocation.cs: interface used to now the exact place where a parse
+       error happens.
+
+       * PageCompiler.cs: generates a couple of methods that are only used in
+       pages.
+
+       * ParseException.cs: use the ILocation interface.
+
+       * TagAttributes.cs: handles the attributes of the tags parsed.
+
+       * TagType.cs: an enum for the different kinds of tags.
+
+       * TemplateControlCompiler.cs: this is the one that does most of the
+       conversion from teh ControlBuilder tree into a CodeDOM tree.
+
+       * UserControlCompiler.cs: simplified as most of the work is done in
+       its base classes.
+
+       * WebServiceCompiler.cs: dummy.
+
 2003-04-20  Gonzalo Paniagua Javier <gonzalo@ximian.com>
 
        * AspComponentFoundry.cs: added GetComponentType method.
index 54f91a30f6189f2acb7f6ba873d0a8dedf7ec64c..8628e31dd0f567abdfaf8cc49c28efa35d017345 100644 (file)
@@ -8,34 +8,26 @@
 //
 
 using System;
+using System.CodeDom.Compiler;
 using System.Web;
-using System.IO;
 
 namespace System.Web.Compilation
 {
        internal class CompilationException : HtmlizedException
        {
-               CompilationResult result;
+               string filename;
+               string errors;
+               string file;
 
-               public CompilationException (CompilationResult result)
-                       : base ("Compilation Error")
+               public CompilationException (string filename, string errors, string file)
                {
-                       this.result = result;
-               }
-
-               public CompilationException (string msg, CompilationResult result)
-                       : base (msg)
-               {
-                       this.result = result;
-               }
-
-               public CompilationException (CompilationCacheItem item)
-               {
-                       this.result = item.Result;
+                       this.filename = filename;
+                       this.errors = errors;
+                       this.file = file;
                }
 
                public override string FileName {
-                       get { return result.FileName; }
+                       get { return filename; }
                }
                
                public override string Title {
@@ -50,25 +42,11 @@ namespace System.Web.Compilation
                }
 
                public override string ErrorMessage {
-                       get {
-                               //FIXME: it should be a one line message.
-                               return result.CompilerOutput;
-                       }
+                       get { return errors; }
                }
 
-               //TODO: get lines from compiler output.
-               public override StringReader SourceError { get {return null;}}
-               public override int SourceErrorLine { get { return -1; } }
-
-               public override TextReader SourceFile {
-                       get {
-                               StreamReader input = new StreamReader (File.OpenRead (FileName));
-                               int sourceErrorLine;
-                               string result = GetErrorLines (input, 0, out sourceErrorLine);
-                               input.Close ();
-                               input = null;
-                               return new StringReader (result);
-                       }
+               public string File {
+                       get { return file; }
                }
        }
 }
diff --git a/mcs/class/System.Web/System.Web.Compilation/CompilationResult.cs b/mcs/class/System.Web/System.Web.Compilation/CompilationResult.cs
deleted file mode 100644 (file)
index 031aeb1..0000000
+++ /dev/null
@@ -1,87 +0,0 @@
-//
-// System.Web.Compilation.CompilationResult
-//
-// Authors:
-//     Gonzalo Paniagua Javier (gonzalo@ximian.com)
-//
-// (C) 2002 Ximian, Inc (http://www.ximian.com)
-//
-using System;
-using System.Collections;
-
-namespace System.Web.Compilation
-{
-       internal class CompilationResult
-       {
-               int exitCode;
-               string fileName;
-               string output;
-               string outputFile;
-               object data;
-               Hashtable options;
-               ArrayList dependencies;
-               
-               public CompilationResult ()
-               {
-               }
-
-               public CompilationResult (string fileName)
-               {
-                       this.fileName = fileName;
-               }
-
-               public void Reset ()
-               {
-                       exitCode = 0;
-                       output = null;
-               }
-
-               public void CopyFrom (CompilationResult other)
-               {
-                       exitCode = other.ExitCode;
-                       output = other.output;
-                       outputFile = other.outputFile;
-                       data = other.data;
-               }
-               
-               public int ExitCode {
-                       get { return exitCode; }
-                       set { exitCode = value; }
-               }
-               
-               public string CompilerOutput {
-                       get { return output; }
-                       set { output = value; }
-               }
-
-               public string FileName {
-                       get { return fileName; }
-               }
-
-               public string OutputFile {
-                       get { return outputFile; }
-                       set { outputFile = value; }
-               }
-
-               public object Data {
-                       get { return data; }
-                       set { data = value; }
-               }
-
-               public Hashtable Options {
-                       get { return options; }
-                       set { options = value; }
-               }
-
-               public ArrayList Dependencies {
-                       get { return dependencies; }
-                       set { dependencies = value; }
-               }
-
-               public override string ToString ()
-               {
-                       return String.Format ("CompilationResult: {0} {1} {2} {3}", exitCode, output, outputFile, data);
-               }
-       }
-}
-
diff --git a/mcs/class/System.Web/System.Web.Compilation/Directive.cs b/mcs/class/System.Web/System.Web.Compilation/Directive.cs
new file mode 100644 (file)
index 0000000..28ef845
--- /dev/null
@@ -0,0 +1,109 @@
+//
+// System.Web.Compilation.Directive
+//
+// Authors:
+//     Gonzalo Paniagua Javier (gonzalo@ximian.com)
+//
+// (C) 2003 Ximian, Inc (http://www.ximian.com)
+//
+
+using System;
+using System.Collections;
+
+namespace System.Web.Compilation
+{
+       sealed class Directive
+       {
+               static Hashtable directivesHash;
+               static string [] page_atts = {  "AspCompat", "AutoEventWireup", "Buffer",
+                                               "ClassName", "ClientTarget", "CodePage",
+                                               "CompilerOptions", "ContentType", "Culture", "Debug",
+                                               "Description", "EnableSessionState", "EnableViewState",
+                                               "EnableViewStateMac", "ErrorPage", "Explicit",
+                                               "Inherits", "Language", "LCID", "ResponseEncoding",
+                                               "Src", "SmartNavigation", "Strict", "Trace",
+                                               "TraceMode", "Transaction", "UICulture",
+                                               "WarningLevel", "CodeBehind" };
+
+               static string [] control_atts = { "AutoEventWireup", "ClassName", "CompilerOptions",
+                                                 "Debug", "Description", "EnableViewState",
+                                                 "Explicit", "Inherits", "Language", "Strict", "Src",
+                                                 "WarningLevel", "CodeBehind", "TargetSchema" };
+
+               static string [] import_atts = { "namespace" };
+               static string [] implements_atts = { "interface" };
+               static string [] assembly_atts = { "name", "src" };
+               static string [] register_atts = { "tagprefix", "tagname", "Namespace", "Src", "Assembly" };
+
+               static string [] outputcache_atts = { "Duration", "Location", "VaryByControl", 
+                                                     "VaryByCustom", "VaryByHeader", "VaryByParam" };
+
+               static string [] reference_atts = { "page", "control" };
+
+               static string [] webservice_atts = { "class", "codebehind", "debug", "language" };
+
+               static string [] application_atts = { "description", "inherits", "codebehind" };
+
+               static Directive ()
+               {
+                       InitHash ();
+               }
+               
+               private static void InitHash ()
+               {
+                       CaseInsensitiveHashCodeProvider provider = new CaseInsensitiveHashCodeProvider ();
+                       CaseInsensitiveComparer comparer =  new CaseInsensitiveComparer ();
+
+                       directivesHash = new Hashtable (provider, comparer); 
+
+                       // Use Hashtable 'cause is O(1) in Contains (ArrayList is O(n))
+                       Hashtable valid_attributes = new Hashtable (provider, comparer);
+                       foreach (string att in page_atts) valid_attributes.Add (att, null);
+                       directivesHash.Add ("PAGE", valid_attributes);
+
+                       valid_attributes = new Hashtable (provider, comparer);
+                       foreach (string att in control_atts) valid_attributes.Add (att, null);
+                       directivesHash.Add ("CONTROL", valid_attributes);
+
+                       valid_attributes = new Hashtable (provider, comparer);
+                       foreach (string att in import_atts) valid_attributes.Add (att, null);
+                       directivesHash.Add ("IMPORT", valid_attributes);
+
+                       valid_attributes = new Hashtable (provider, comparer);
+                       foreach (string att in implements_atts) valid_attributes.Add (att, null);
+                       directivesHash.Add ("IMPLEMENTS", valid_attributes);
+
+                       valid_attributes = new Hashtable (provider, comparer);
+                       foreach (string att in register_atts) valid_attributes.Add (att, null);
+                       directivesHash.Add ("REGISTER", valid_attributes);
+
+                       valid_attributes = new Hashtable (provider, comparer);
+                       foreach (string att in assembly_atts) valid_attributes.Add (att, null);
+                       directivesHash.Add ("ASSEMBLY", valid_attributes);
+
+                       valid_attributes = new Hashtable (provider, comparer);
+                       foreach (string att in outputcache_atts) valid_attributes.Add (att, null);
+                       directivesHash.Add ("OUTPUTCACHE", valid_attributes);
+
+                       valid_attributes = new Hashtable (provider, comparer);
+                       foreach (string att in reference_atts) valid_attributes.Add (att, null);
+                       directivesHash.Add ("REFERENCE", valid_attributes);
+
+                       valid_attributes = new Hashtable (provider, comparer);
+                       foreach (string att in webservice_atts) valid_attributes.Add (att, null);
+                       directivesHash.Add ("WEBSERVICE", valid_attributes);
+
+                       valid_attributes = new Hashtable (provider, comparer);
+                       foreach (string att in application_atts) valid_attributes.Add (att, null);
+                       directivesHash.Add ("APPLICATION", valid_attributes);
+               }
+               
+               private Directive () { }
+
+               public static bool IsDirective (string id)
+               {
+                       return directivesHash.Contains (id);
+               }
+       }
+}
+
index e8bdda9ca6da29934f9a91ff1095e2b43c3ca1b9..c841b643766956a126c563dfd2ed315884f01e36 100644 (file)
@@ -4,96 +4,33 @@
 // Authors:
 //     Gonzalo Paniagua Javier (gonzalo@ximian.com)
 //
-// (C) 2002 Ximian, Inc (http://www.ximian.com)
+// (C) 2002,2003 Ximian, Inc (http://www.ximian.com)
 //
 using System;
-using System.IO;
-using System.Reflection;
-using System.Text;
-using System.Web;
-using System.Web.Util;
+using System.Web.UI;
 
 namespace System.Web.Compilation
 {
        class GlobalAsaxCompiler : BaseCompiler
        {
-               string filename;
-               string sourceFile;
-               HttpContext context;
+               ApplicationFileParser parser;
 
-               private GlobalAsaxCompiler (string filename)
+               public GlobalAsaxCompiler (ApplicationFileParser parser)
+                       : base (parser)
                {
-                       this.filename = filename;
+                       this.parser = parser;
                }
 
-               public override Type GetCompiledType ()
+               public static Type CompileApplicationType (ApplicationFileParser parser)
                {
-                       sourceFile = GenerateSourceFile ();
-
-                       CachingCompiler compiler = new CachingCompiler (this);
-                       CompilationResult result = new CompilationResult (sourceFile);
-                       result.Options = options;
-                       if (compiler.Compile (result) == false)
-                               throw new CompilationException (result);
-                       
-                       result.Dependencies = dependencies;
-                       Assembly assembly = Assembly.LoadFrom (result.OutputFile);
-                       Type [] types = assembly.GetTypes ();
-                       foreach (Type t in types) {
-                               if (t.IsSubclassOf (typeof (HttpApplication))) {
-                                       if (result.Data != null)
-                                               throw new CompilationException ("More that 1 app!!!", result);
-                                       result.Data = t;
-                               }
-                       }
-
-                       return result.Data as Type;
-               }
-
-               public override string Key {
-                       get {
-                               return filename;
-                       }
-               }
-
-               public override string SourceFile {
-                       get {
-                               return sourceFile;
-                       }
+                       GlobalAsaxCompiler compiler = new GlobalAsaxCompiler (parser);
+                       return compiler.GetCompiledType ();
                }
 
-               public static Type CompileApplicationType (string filename, HttpContext context)
+               [MonoTODO("Process application scope for object tags")]
+               protected override void ProcessObjectTag (ObjectTagBuilder tag)
                {
-                       CompilationCacheItem item = CachingCompiler.GetCached (filename);
-                       if (item != null && item.Result != null) {
-                               if (item.Result != null)
-                                       return item.Result.Data as Type;
-
-                               throw new CompilationException (item.Result);
-                       }
-
-                       GlobalAsaxCompiler gac = new GlobalAsaxCompiler (filename);
-                       gac.context = context;
-                       return gac.GetCompiledType ();
-               }
-
-               string GenerateSourceFile ()
-               {
-                       AspGenerator generator = new AspGenerator (filename);
-                       generator.Context = context;
-                       generator.BaseType = typeof (HttpApplication).ToString ();
-                       generator.ProcessElements ();
-                       string generated = generator.GetCode ().ReadToEnd ();
-                       options = generator.Options;
-                       dependencies = generator.Dependencies;
-
-                       //FIXME: should get Tmp dir for this application
-                       string csName = Path.GetTempFileName () + ".cs";
-                       WebTrace.WriteLine ("Writing {0}", csName);
-                       StreamWriter output = new StreamWriter (File.OpenWrite (csName));
-                       output.Write (generated);
-                       output.Close ();
-                       return csName;
+                       //TODO
                }
        }
 }
diff --git a/mcs/class/System.Web/System.Web.Compilation/ILocation.cs b/mcs/class/System.Web/System.Web.Compilation/ILocation.cs
new file mode 100644 (file)
index 0000000..8df31f7
--- /dev/null
@@ -0,0 +1,22 @@
+//
+// System.Web.Compilation.ILocation
+//
+// Authors:
+//     Gonzalo Paniagua Javier (gonzalo@ximian.com)
+//
+// (C) 2003 Ximian, Inc (http://www.ximian.com)
+//
+
+namespace System.Web.Compilation
+{
+       interface ILocation
+       {
+               string Filename { get; }
+               int BeginLine { get; }
+               int EndLine { get; }
+               int BeginColumn { get; }
+               int EndColumn { get; }
+               string PlainText { get; }
+       }
+}
+
index 566eb146f2840d04fc6bf3991d37851c95233fa2..1935254170ba5ce4fce9173468d96deb5f7bc2f2 100644 (file)
@@ -7,97 +7,59 @@
 // (C) 2002,2003 Ximian, Inc (http://www.ximian.com)
 //
 using System;
+using System.CodeDom;
 using System.IO;
 using System.Reflection;
 using System.Text;
 using System.Web.UI;
+using System.Web.SessionState;
 using System.Web.Util;
 
 namespace System.Web.Compilation
 {
-       class PageCompiler : BaseCompiler
+       class PageCompiler : TemplateControlCompiler
        {
                PageParser pageParser;
-               string sourceFile;
+               static CodeTypeReference intRef = new CodeTypeReference (typeof (int));
 
-               private PageCompiler (PageParser pageParser)
+               public PageCompiler (PageParser pageParser)
+                       : base (pageParser)
                {
                        this.pageParser = pageParser;
                }
 
-               public override Type GetCompiledType ()
+               protected override void AddInterfaces () 
                {
-                       string inputFile = pageParser.InputFile;
-                       sourceFile = GenerateSourceFile ();
+                       base.AddInterfaces ();
+                       if (pageParser.EnableSessionState)
+                               mainClass.BaseTypes.Add (new CodeTypeReference (typeof(IRequiresSessionState)));
 
-                       CachingCompiler compiler = new CachingCompiler (this);
-                       CompilationResult result = new CompilationResult (sourceFile);
-                       result.Options = options;
-                       if (compiler.Compile (result) == false)
-                               throw new CompilationException (result);
-                       
-                       result.Dependencies = dependencies;
-                       if (result.Data is Type)
-                               return (Type) result.Data;
-
-                       Assembly assembly = Assembly.LoadFrom (result.OutputFile);
-                       Type [] types = assembly.GetTypes ();
-                       foreach (Type t in types) {
-                               if (t.IsSubclassOf (typeof (Page))) {
-                                       if (result.Data != null)
-                                               throw new CompilationException ("More that 1 page!!!", result);
-                                       result.Data = t;
-                               }
-                       }
-
-                       return result.Data as Type;
+                       if (pageParser.ReadOnlySessionState)
+                               mainClass.BaseTypes.Add (new CodeTypeReference (typeof (IReadOnlySessionState)));
                }
 
-               public override string Key {
-                       get {
-                               return pageParser.InputFile;
-                       }
-               }
-
-               public override string SourceFile {
-                       get {
-                               return sourceFile;
-                       }
+               void CreateGetTypeHashCode () 
+               {
+                       CodeMemberMethod method = new CodeMemberMethod ();
+                       method.ReturnType = intRef;
+                       method.Name = "GetTypeHashCode";
+                       method.Attributes = MemberAttributes.Public | MemberAttributes.Override;
+                       Random rnd = new Random (pageParser.InputFile.GetHashCode ());
+                       method.Statements.Add (new CodeMethodReturnStatement (new CodePrimitiveExpression (rnd.Next ())));
+                       mainClass.Members.Add (method);
                }
 
-               public static Type CompilePageType (PageParser pageParser)
+               protected override void CreateMethods ()
                {
-                       CompilationCacheItem item = CachingCompiler.GetCached (pageParser.InputFile);
-                       if (item != null && item.Result != null) {
-                               if (item.Result != null) {
-                                       pageParser.Options = item.Result.Options;
-                                       return item.Result.Data as Type;
-                               }
-
-                               throw new CompilationException (item.Result);
-                       }
+                       base.CreateMethods ();
 
-                       PageCompiler pc = new PageCompiler (pageParser);
-                       return pc.GetCompiledType ();
+                       CreateGetTypeHashCode ();
                }
 
-               string GenerateSourceFile ()
+               public static Type CompilePageType (PageParser pageParser)
                {
-                       AspGenerator generator = new AspGenerator (pageParser.InputFile);
-                       generator.Context = pageParser.Context;
-                       generator.BaseType = pageParser.BaseType.ToString ();
-                       generator.ProcessElements ();
-                       pageParser.Text = generator.GetCode ().ReadToEnd ();
-                       dependencies = generator.Dependencies;
-                       options = generator.Options;
-
-                       //FIXME: should get Tmp dir for this application
-                       string csName = Path.GetTempFileName () + ".cs";
-                       WebTrace.WriteLine ("Writing {0}", csName);
-                       StreamWriter output = new StreamWriter (File.OpenWrite (csName));
-                       output.Write (pageParser.Text);
-                       output.Close ();
-                       return csName;
+                       PageCompiler compiler = new PageCompiler (pageParser);
+                       return compiler.GetCompiledType ();
                }
        }
 }
index 829a107bc268c82071ee02eae0e466fa116d6dbf..2520cb510e27624a4057cac062a51bcd36e5f337 100644 (file)
@@ -14,28 +14,15 @@ namespace System.Web.Compilation
 {
        internal class ParseException : HtmlizedException
        {
-               string fileName;
                string message;
-               int line;
-               int col;
-               int sourceErrorLine;
+               ILocation location;
 
-               public ParseException (string fileName, string message, int line, int col)
-                       : base (message)
+               public ParseException (ILocation location, string message)
                {
-                       this.fileName = fileName;
+                       if (location == null)
+                               throw new Exception ();
+                       this.location = location;
                        this.message = message;
-                       this.line = line >= 1 ? line : 1;
-                       this.col = col;
-               }
-               
-               public ParseException (string fileName, string message, int line, int col, Exception inner)
-                       : base (message, inner)
-               {
-                       this.fileName = fileName;
-                       this.message = message;
-                       this.line = line >= 1 ? line : 1;
-                       this.col = col;
                }
 
                public override string Title {
@@ -54,25 +41,7 @@ namespace System.Web.Compilation
                }
 
                public override string FileName {
-                       get { return fileName; }
-               }
-               
-               public override StringReader SourceError {
-                       get {
-                               StreamReader input = new StreamReader (File.OpenRead (fileName));
-                               string result = GetErrorLines (input, line - 1, out sourceErrorLine);
-                               input.Close ();
-                               input = null;
-                               return new StringReader (result);
-                       }
-               }
-
-               public override int SourceErrorLine {
-                       get { return sourceErrorLine; }
-               }
-
-               public override TextReader SourceFile {
-                       get { return null; }
+                       get { return location.Filename; }
                }
        }
 }
diff --git a/mcs/class/System.Web/System.Web.Compilation/TagAttributes.cs b/mcs/class/System.Web/System.Web.Compilation/TagAttributes.cs
new file mode 100644 (file)
index 0000000..50d2c30
--- /dev/null
@@ -0,0 +1,158 @@
+//
+// System.Web.Compilation.TagAttributes
+//
+// Authors:
+//     Gonzalo Paniagua Javier (gonzalo@ximian.com)
+//
+// (C) 2003 Ximian, Inc (http://www.ximian.com)
+//
+
+using System;
+using System.Collections;
+using System.Text;
+
+namespace System.Web.Compilation
+{
+       class TagAttributes
+       {
+               Hashtable atts_hash;
+               Hashtable tmp_hash;
+               ArrayList keys;
+               ArrayList values;
+               bool got_hashed;
+
+               public TagAttributes ()
+               {
+                       got_hashed = false;
+                       keys = new ArrayList ();
+                       values = new ArrayList ();
+               }
+
+               void MakeHash ()
+               {
+                       atts_hash = new Hashtable (CaseInsensitiveHashCodeProvider.Default,
+                                                  CaseInsensitiveComparer.Default);
+                       for (int i = 0; i < keys.Count; i++)
+                               atts_hash.Add (keys [i], values [i]);
+                       got_hashed = true;
+                       keys = null;
+                       values = null;
+               }
+               
+               public bool IsRunAtServer ()
+               {
+                       return got_hashed;
+               }
+
+               public void Add (object key, object value)
+               {
+                       if (key != null && value != null &&
+                           0 == String.Compare ((string) key,  "runat", true)) {
+                               if (0 == String.Compare ((string) value,  "server", true))
+                                       MakeHash ();
+                               else
+                                       throw new HttpException ("runat attribute must have a 'server' value");
+                       }
+
+                       if (got_hashed) {
+                               atts_hash [key] = value;
+                       } else {
+                               keys.Add (key);
+                               values.Add (value);
+                       }
+               }
+               
+               public ICollection Keys 
+               {
+                       get { return (got_hashed ? atts_hash.Keys : keys); }
+               }
+
+               public ICollection Values 
+               {
+                       get { return (got_hashed ? atts_hash.Values : values); }
+               }
+
+               private int CaseInsensitiveSearch (string key)
+               {
+                       // Hope not to have many attributes when the tag is not a server tag...
+                       for (int i = 0; i < keys.Count; i++){
+                               if (0 == String.Compare ((string) keys [i], key, true))
+                                       return i;
+                       }
+                       return -1;
+               }
+               
+               public object this [object key]
+               {
+                       get {
+                               if (got_hashed)
+                                       return atts_hash [key];
+
+                               int idx = CaseInsensitiveSearch ((string) key);
+                               if (idx == -1)
+                                       return null;
+                                               
+                               return values [idx];
+                       }
+
+                       set {
+                               if (got_hashed)
+                                       atts_hash [key] = value;
+                               else {
+                                       int idx = CaseInsensitiveSearch ((string) key);
+                                       keys [idx] = value;
+                               }
+                       }
+               }
+               
+               public int Count 
+               {
+                       get { return (got_hashed ? atts_hash.Count : keys.Count);}
+               }
+
+               public bool IsDataBound (string att)
+               {
+                       if (att == null || !got_hashed)
+                               return false;
+
+                       return (att.StartsWith ("<%#") && att.EndsWith ("%>"));
+               }
+               
+               public Hashtable GetDictionary (string key)
+               {
+                       if (got_hashed)
+                               return atts_hash;
+
+                       if (tmp_hash == null)
+                               tmp_hash = new Hashtable (CaseInsensitiveHashCodeProvider.Default,
+                                                         CaseInsensitiveComparer.Default);
+                       
+                       tmp_hash.Clear ();
+                       for (int i = keys.Count - 1; i >= 0; i--)
+                               if (key == null || String.Compare (key, (string) keys [i], true) == 0)
+                                       tmp_hash [keys [i]] = values [i];
+
+                       return tmp_hash;
+               }
+               
+               public override string ToString ()
+               {
+                       StringBuilder result = new StringBuilder ();
+                       string value;
+                       foreach (string key in Keys){
+                               result.Append (key);
+                               value = this [key] as string;
+                               if (value != null)
+                                       result.AppendFormat ("=\"{0}\"", value);
+
+                               result.Append (' ');
+                       }
+
+                       if (result.Length > 0 && result [result.Length - 1] == ' ')
+                               result.Length--;
+                               
+                       return result.ToString ();
+               }
+       }
+}
+
diff --git a/mcs/class/System.Web/System.Web.Compilation/TagType.cs b/mcs/class/System.Web/System.Web.Compilation/TagType.cs
new file mode 100644 (file)
index 0000000..4d8eed5
--- /dev/null
@@ -0,0 +1,24 @@
+//
+// System.Web.Compilation.TagType
+//
+// Authors:
+//     Gonzalo Paniagua Javier (gonzalo@ximian.com)
+//
+// (C) 2003 Ximian, Inc (http://www.ximian.com)
+//
+namespace System.Web.Compilation
+{
+       enum TagType
+       {
+               Text,
+               Tag,
+               Close,
+               SelfClosing,
+               Directive,
+               ServerComment,
+               DataBinding,
+               CodeRender,
+               CodeRenderExpression
+       }
+}
+
diff --git a/mcs/class/System.Web/System.Web.Compilation/TemplateControlCompiler.cs b/mcs/class/System.Web/System.Web.Compilation/TemplateControlCompiler.cs
new file mode 100644 (file)
index 0000000..68d55f7
--- /dev/null
@@ -0,0 +1,864 @@
+//
+// System.Web.Compilation.TemplateControlCompiler
+//
+// Authors:
+//     Gonzalo Paniagua Javier (gonzalo@ximian.com)
+//
+// (C) 2003 Ximian, Inc (http://www.ximian.com)
+//
+using System;
+using System.CodeDom;
+using System.Collections;
+using System.ComponentModel;
+using System.Drawing;
+using System.Globalization;
+using System.Reflection;
+using System.Text;
+using System.Web.UI;
+
+namespace System.Web.Compilation
+{
+       class TemplateControlCompiler : BaseCompiler
+       {
+               static BindingFlags noCaseFlags = BindingFlags.Public | BindingFlags.NonPublic |
+                                                 BindingFlags.Instance | BindingFlags.IgnoreCase;
+
+               static Type styleType = typeof (System.Web.UI.WebControls.Style);
+               static Type fontinfoType = typeof (System.Web.UI.WebControls.FontInfo);
+
+               TemplateControlParser parser;
+               static TypeConverter colorConverter;
+
+               static CodeVariableReferenceExpression ctrlVar = new CodeVariableReferenceExpression ("__ctrl");
+               static Type [] arrayString = new Type [] {typeof (string)};
+               static Type [] arrayStringCultureInfo = new Type [] {typeof (string), typeof (CultureInfo)};
+
+               public TemplateControlCompiler (TemplateControlParser parser)
+                       : base (parser)
+               {
+                       this.parser = parser;
+               }
+
+               void EnsureID (ControlBuilder builder)
+               {
+                       if (builder.ID == null || builder.ID.Trim () == "")
+                               builder.ID = builder.GetNextID (null);
+               }
+
+               void CreateField (ControlBuilder builder, bool check)
+               {
+                       if (check && CheckBaseFieldOrProperty (builder.ID, builder.ControlType))
+                               return; // The field or property already exists in a base class and is accesible.
+
+                       CodeMemberField field;
+                       field = new CodeMemberField (builder.ControlType.FullName, builder.ID);
+                       field.Attributes = MemberAttributes.Family;
+                       mainClass.Members.Add (field);
+               }
+
+               bool CheckBaseFieldOrProperty (string id, Type type)
+               {
+                       FieldInfo fld = parser.BaseType.GetField (id, noCaseFlags);
+
+                       Type other = null;
+                       if (fld == null || fld.IsPrivate) {
+                               PropertyInfo prop = parser.BaseType.GetProperty (id, noCaseFlags);
+                               if (prop != null) {
+                                       MethodInfo setm = prop.GetSetMethod (true);
+                                       if (setm != null)
+                                               other = prop.PropertyType;
+                               }
+                       } else {
+                               other = fld.FieldType;
+                       }
+                       
+                       if (other == null)
+                               return false;
+
+                       if (!other.IsAssignableFrom (type)) {
+                               string msg = String.Format ("The base class includes the field '{0}', but its " +
+                                                           "type '{1}' is not compatible with {2}",
+                                                           id, other, type);
+                               throw new HttpException (msg);
+                       }
+
+                       return true;
+               }
+
+               void AddParsedSubObjectStmt (ControlBuilder builder, CodeExpression expr) 
+               {
+                       if (!builder.haveParserVariable) {
+                               CodeVariableDeclarationStatement p = new CodeVariableDeclarationStatement();
+                               p.Name = "__parser";
+                               p.Type = new CodeTypeReference (typeof (IParserAccessor));
+                               p.InitExpression = new CodeCastExpression (typeof (IParserAccessor), ctrlVar);
+                               builder.method.Statements.Add (p);
+                               builder.haveParserVariable = true;
+                       }
+
+                       CodeVariableReferenceExpression var = new CodeVariableReferenceExpression ("__parser");
+                       CodeMethodInvokeExpression invoke = new CodeMethodInvokeExpression (var, "AddParsedSubObject");
+                       invoke.Parameters.Add (expr);
+                       builder.method.Statements.Add (invoke);
+               }
+
+               void InitMethod (ControlBuilder builder, bool isTemplate, bool childrenAsProperties)
+               {
+                       string tailname = ((builder is RootBuilder) ? "Tree" : ("_" + builder.ID));
+                       CodeMemberMethod method = new CodeMemberMethod ();
+                       builder.method = method;
+                       method.Name = "__BuildControl" + tailname;
+                       method.Attributes = MemberAttributes.Private | MemberAttributes.Final;
+                       Type type = builder.ControlType;
+
+                       if (builder.HasAspCode) {
+                               CodeMemberMethod renderMethod = new CodeMemberMethod ();
+                               builder.renderMethod = renderMethod;
+                               renderMethod.Name = "__Render" + tailname;
+                               renderMethod.Attributes = MemberAttributes.Private | MemberAttributes.Final;
+                               CodeParameterDeclarationExpression arg1 = new CodeParameterDeclarationExpression ();
+                               arg1.Type = new CodeTypeReference (typeof (HtmlTextWriter));
+                               arg1.Name = "__output";
+                               CodeParameterDeclarationExpression arg2 = new CodeParameterDeclarationExpression ();
+                               arg2.Type = new CodeTypeReference (typeof (Control));
+                               arg2.Name = "parameterContainer";
+                               renderMethod.Parameters.Add (arg1);
+                               renderMethod.Parameters.Add (arg2);
+                               mainClass.Members.Add (renderMethod);
+                       }
+                       
+                       if (childrenAsProperties || isTemplate) {
+                               string typeString;
+                               if (builder.isProperty && !isTemplate)
+                                       typeString = builder.ControlType.FullName;
+                               else 
+                                       typeString = "System.Web.UI.Control";
+
+                               method.Parameters.Add (new CodeParameterDeclarationExpression (typeString, "__ctrl"));
+                       } else {
+                               
+                               if (typeof (Control).IsAssignableFrom (type))
+                                       method.ReturnType = new CodeTypeReference (typeof (Control));
+
+                               CodeObjectCreateExpression newExpr = new CodeObjectCreateExpression (type);
+
+                               object [] atts = type.GetCustomAttributes (typeof (ConstructorNeedsTagAttribute), true);
+                               if (atts != null && atts.Length > 0) {
+                                       ConstructorNeedsTagAttribute att = (ConstructorNeedsTagAttribute) atts [0];
+                                       if (att.NeedsTag)
+                                               newExpr.Parameters.Add (new CodePrimitiveExpression (builder.TagName));
+                               } else if (builder is DataBindingBuilder) {
+                                       newExpr.Parameters.Add (new CodePrimitiveExpression (0));
+                                       newExpr.Parameters.Add (new CodePrimitiveExpression (1));
+                               }
+
+                               method.Statements.Add (new CodeVariableDeclarationStatement (builder.ControlType, "__ctrl"));
+                               CodeAssignStatement assign = new CodeAssignStatement ();
+                               assign.Left = ctrlVar;
+                               assign.Right = newExpr;
+                               method.Statements.Add (assign);
+                               
+                               CodeFieldReferenceExpression builderID = new CodeFieldReferenceExpression ();
+                               builderID.TargetObject = thisRef;
+                               builderID.FieldName = builder.ID;
+                               assign = new CodeAssignStatement ();
+                               assign.Left = builderID;
+                               assign.Right = ctrlVar;
+                               method.Statements.Add (assign);
+                               if (typeof (UserControl).IsAssignableFrom (type)) {
+                                       CodeMethodReferenceExpression mref = new CodeMethodReferenceExpression ();
+                                       mref.TargetObject = builderID;
+                                       mref.MethodName = "InitializeAsUserControl";
+                                       CodeMethodInvokeExpression initAsControl = new CodeMethodInvokeExpression (mref);
+                                       initAsControl.Parameters.Add (new CodePropertyReferenceExpression (thisRef, "Page"));
+                                       method.Statements.Add (initAsControl);
+                               }
+                       }
+
+                       mainClass.Members.Add (method);
+               }
+
+               void AddLiteralSubObject (ControlBuilder builder, string str)
+               {
+                       if (!builder.HasAspCode) {
+                               CodeObjectCreateExpression expr;
+                               expr = new CodeObjectCreateExpression (typeof (LiteralControl), new CodePrimitiveExpression (str));
+                               AddParsedSubObjectStmt (builder, expr);
+                       } else {
+                               CodeMethodReferenceExpression methodRef = new CodeMethodReferenceExpression ();
+                               methodRef.TargetObject = new CodeArgumentReferenceExpression ("__output");
+                               methodRef.MethodName = "Write";
+
+                               CodeMethodInvokeExpression expr;
+                               expr = new CodeMethodInvokeExpression (methodRef, new CodePrimitiveExpression (str));
+                               builder.renderMethod.Statements.Add (expr);
+                       }
+               }
+
+               void AddCodeForPropertyOrField (CodeMemberMethod method, Type type, string var_name, string att, bool isDataBound)
+               {
+                       if (isDataBound) {
+                               //DataBoundProperty (type, var_name, att);
+                               return;
+                       }
+
+                       CodeAssignStatement assign = new CodeAssignStatement ();
+                       assign.Left = new CodePropertyReferenceExpression (ctrlVar, var_name);
+                       assign.Right = GetExpressionFromString (type, att);
+
+                       method.Statements.Add (assign);
+               }
+
+               bool ProcessPropertiesAndFields (CodeMemberMethod method, MemberInfo member, string id, string attValue)
+               {
+                       int hyphen = id.IndexOf ('-');
+
+                       bool isPropertyInfo = (member is PropertyInfo);
+
+                       bool is_processed = false;
+                       //FIXME: bool isDataBound = att.IsDataBound ((string) att [id]);
+                       bool isDataBound = false;
+                       Type type;
+                       if (isPropertyInfo) {
+                               type = ((PropertyInfo) member).PropertyType;
+                               if (hyphen == -1 && ((PropertyInfo) member).CanWrite == false)
+                                       return false;
+                       } else {
+                               type = ((FieldInfo) member).FieldType;
+                       }
+
+                       if (0 == String.Compare (member.Name, id, true)){
+                               AddCodeForPropertyOrField (method, type, member.Name, attValue, isDataBound);
+                               is_processed = true;
+                       } else if (hyphen != -1 && (type == fontinfoType || type == styleType || type.IsSubclassOf (styleType))){
+                               //FIXME: x-y should not be limited to style and font
+                               string prop_field = id.Replace ("-", ".");
+                               string [] parts = prop_field.Split (new char [] {'.'});
+                               if (parts.Length != 2 || 0 != String.Compare (member.Name, parts [0], true))
+                                       return false;
+
+                               PropertyInfo [] subprops = type.GetProperties ();
+                               foreach (PropertyInfo subprop in subprops) {
+                                       if (0 != String.Compare (subprop.Name, parts [1], true))
+                                               continue;
+
+                                       if (subprop.CanWrite == false)
+                                               return false;
+
+                                       bool is_bool = subprop.PropertyType == typeof (bool);
+                                       if (!is_bool && attValue == null)
+                                               return false; // Font-Size -> Font-Size="" as html
+
+                                       string value;
+                                       if (attValue == null && is_bool)
+                                               value = "true"; // Font-Bold <=> Font-Bold="true"
+                                       else
+                                               value = attValue;
+
+                                       AddCodeForPropertyOrField (method, subprop.PropertyType,
+                                                        member.Name + "." + subprop.Name,
+                                                        value, isDataBound);
+                                       is_processed = true;
+                               }
+                       }
+
+                       return is_processed;
+               }
+
+               void AddEventAssign (CodeMemberMethod method, string name, Type type, string value)
+               {
+                       //"__ctrl.{0} += new {1} (this.{2});"
+                       CodeEventReferenceExpression evtID = new CodeEventReferenceExpression (ctrlVar, name);
+
+                       CodeDelegateCreateExpression create;
+                       create = new CodeDelegateCreateExpression (new CodeTypeReference (type), thisRef, value);
+
+                       CodeAttachEventStatement attach = new CodeAttachEventStatement (evtID, create);
+                       method.Statements.Add (attach);
+               }
+               
+               void CreateAssignStatementsFromAttributes (ControlBuilder builder)
+               {
+                       IDictionary atts = builder.attribs;
+                       if (atts == null || atts.Count == 0)
+                               return;
+
+                       EventInfo [] ev_info = null;
+                       PropertyInfo [] prop_info = null;
+                       FieldInfo [] field_info = null;
+                       bool is_processed = false;
+                       Type type = builder.ControlType;
+
+                       foreach (string id in atts.Keys){
+                               if (0 == String.Compare (id, "runat", true))
+                                       continue;
+
+                               is_processed = false;
+                               if (id.Length > 2 && id.Substring (0, 2).ToUpper () == "ON"){
+                                       if (ev_info == null)
+                                               ev_info = type.GetEvents ();
+
+                                       string id_as_event = id.Substring (2);
+                                       foreach (EventInfo ev in ev_info){
+                                               if (0 == String.Compare (ev.Name, id_as_event, true)){
+                                                       AddEventAssign (builder.method,
+                                                                       ev.Name,
+                                                                       ev.EventHandlerType,
+                                                                       (string) atts [id]);
+
+                                                       is_processed = true;
+                                                       break;
+                                               }
+                                       }
+
+                                       if (is_processed)
+                                               continue;
+                               } 
+
+                               if (prop_info == null)
+                                       prop_info = type.GetProperties ();
+
+                               foreach (PropertyInfo prop in prop_info) {
+                                       is_processed = ProcessPropertiesAndFields (builder.method, prop, id, atts [id] as string);
+                                       if (is_processed)
+                                               break;
+                               }
+
+                               if (is_processed)
+                                       continue;
+
+                               if (field_info == null)
+                                       field_info = type.GetFields ();
+
+                               foreach (FieldInfo field in field_info){
+                                       is_processed = ProcessPropertiesAndFields (builder.method, field, id, atts [id] as string);
+                                       if (is_processed)
+                                               break;
+                               }
+
+                               if (is_processed)
+                                       continue;
+
+                               if (!typeof (IAttributeAccessor).IsAssignableFrom (type))
+                                       throw new ParseException (builder.location, "Unrecognized attribute: " + id);
+
+
+                               CodeCastExpression cast = new CodeCastExpression (typeof (IAttributeAccessor), ctrlVar);
+                               CodeMethodReferenceExpression methodExpr;
+                               methodExpr = new CodeMethodReferenceExpression (cast, "SetAttribute");
+                               CodeMethodInvokeExpression expr = new CodeMethodInvokeExpression (methodExpr);
+                               expr.Parameters.Add (new CodePrimitiveExpression (id));
+                               expr.Parameters.Add (new CodePrimitiveExpression ((string) atts [id]));
+                               builder.method.Statements.Add (expr);
+                       }
+               }
+
+               void AddRenderControl (ControlBuilder builder)
+               {
+                       CodeIndexerExpression indexer = new CodeIndexerExpression ();
+                       indexer.TargetObject = new CodePropertyReferenceExpression (
+                                                       new CodeArgumentReferenceExpression ("parameterContainer"),
+                                                       "Controls");
+                                                       
+                       indexer.Indices.Add (new CodePrimitiveExpression (builder.renderIndex));
+                       
+                       CodeMethodInvokeExpression invoke = new CodeMethodInvokeExpression (indexer, "RenderControl");
+                       invoke.Parameters.Add (new CodeArgumentReferenceExpression ("__output"));
+                       builder.renderMethod.Statements.Add (invoke);
+                       builder.renderIndex++;
+               }
+
+               void AddChildCall (ControlBuilder parent, ControlBuilder child)
+               {
+                       CodeMethodReferenceExpression m = new CodeMethodReferenceExpression (thisRef, child.method.Name);
+                       CodeMethodInvokeExpression expr = new CodeMethodInvokeExpression (m);
+                       if (child.isProperty || parent.FChildrenAsProperties) {
+                               expr.Parameters.Add (new CodeFieldReferenceExpression (ctrlVar, child.TagName));
+                               parent.method.Statements.Add (expr);
+                               return;
+                       }
+
+                       parent.method.Statements.Add (expr);
+                       CodeFieldReferenceExpression field = new CodeFieldReferenceExpression (thisRef, child.ID);
+                       if (parent.ControlType == null || typeof (IParserAccessor).IsAssignableFrom (parent.ControlType)) {
+                               AddParsedSubObjectStmt (parent, field);
+                       } else {
+                               CodeMethodInvokeExpression invoke = new CodeMethodInvokeExpression (ctrlVar, "Add");
+                               invoke.Parameters.Add (field);
+                               parent.method.Statements.Add (invoke);
+                       }
+                               
+                       if (parent.HasAspCode)
+                               AddRenderControl (parent);
+               }
+
+               void AddTemplateInvocation (CodeMemberMethod method, string name, string methodName)
+               {
+                       CodePropertyReferenceExpression prop = new CodePropertyReferenceExpression (ctrlVar, name);
+
+                       CodeObjectCreateExpression newBuild = new CodeObjectCreateExpression (typeof (BuildTemplateMethod));
+                       newBuild.Parameters.Add (new CodeMethodReferenceExpression (thisRef, methodName));
+
+                       CodeObjectCreateExpression newCompiled = new CodeObjectCreateExpression (typeof (CompiledTemplateBuilder));
+                       newCompiled.Parameters.Add (newBuild);
+
+                       CodeAssignStatement assign = new CodeAssignStatement (prop, newCompiled);
+                       method.Statements.Add (assign);
+               }
+
+               void AddCodeRender (ControlBuilder parent, CodeRenderBuilder cr)
+               {
+                       if (cr.Code == null || cr.Code.Trim () == "")
+                               return;
+
+                       if (!cr.IsAssign) {
+                               CodeSnippetStatement code = new CodeSnippetStatement (cr.Code);
+                               parent.renderMethod.Statements.Add (code);
+                               return;
+                       }
+
+                       CodeMethodInvokeExpression expr = new CodeMethodInvokeExpression ();
+                       expr.Method = new CodeMethodReferenceExpression (
+                                                       new CodeArgumentReferenceExpression ("__output"),
+                                                       "Write");
+
+                       expr.Parameters.Add (new CodeSnippetExpression (cr.Code));
+                       parent.renderMethod.Statements.Add (expr);
+               }
+
+               static Type GetContainerType (ControlBuilder builder)
+               {
+                       Type type = builder.NamingContainerType;
+                       if (builder.ControlType != null && !typeof (ITemplate).IsAssignableFrom (builder.ControlType))
+                               return type;
+
+                       PropertyInfo prop = type.GetProperty ("Items", noCaseFlags);
+                       if (prop == null)
+                               return type;
+
+                       Type ptype = prop.PropertyType;
+                       if (!typeof (ICollection).IsAssignableFrom (ptype))
+                               return type;
+
+                       prop = ptype.GetProperty ("Item", noCaseFlags);
+                       if (prop == null)
+                               return type;
+
+                       return prop.PropertyType;
+               }
+               
+               void AddDataBindingLiteral (ControlBuilder builder, DataBindingBuilder db)
+               {
+                       if (db.Code == null || db.Code.Trim () == "")
+                               return;
+
+                       EnsureID (db);
+                       CreateField (db, false);
+
+                       string dbMethodName = "__DataBind_" + db.ID;
+                       // Add the method that builds the DataBoundLiteralControl
+                       InitMethod (db, false, false);
+                       CodeMemberMethod method = db.method;
+                       AddEventAssign (method, "DataBinding", typeof (EventHandler), dbMethodName);
+                       method.Statements.Add (new CodeMethodReturnStatement (ctrlVar));
+
+                       // Add the DataBind handler
+                       CodeTypeReference dbTypeRef = new CodeTypeReference (typeof (DataBoundLiteralControl));
+                       CodeTypeReference containerType = new CodeTypeReference (GetContainerType (builder));
+
+                       method = new CodeMemberMethod ();
+                       method.Attributes = MemberAttributes.Public | MemberAttributes.Final;
+                       method.Name = dbMethodName;
+                       method.Parameters.Add (new CodeParameterDeclarationExpression (typeof (object), "sender"));
+                       method.Parameters.Add (new CodeParameterDeclarationExpression (typeof (EventArgs), "e"));
+
+                       CodeVariableDeclarationStatement decl = new CodeVariableDeclarationStatement();
+                       decl.Name = "Container";
+                       decl.Type = containerType;
+                       method.Statements.Add (decl);
+
+                       decl = new CodeVariableDeclarationStatement();
+                       decl.Name = "target";
+                       decl.Type = dbTypeRef;
+                       method.Statements.Add (decl);
+
+                       CodeVariableReferenceExpression target = new CodeVariableReferenceExpression ("target");
+                       CodeAssignStatement assign = new CodeAssignStatement ();
+                       assign.Left = target;
+                       assign.Right = new CodeCastExpression (dbTypeRef, new CodeArgumentReferenceExpression ("sender"));
+                       method.Statements.Add (assign);
+
+                       assign = new CodeAssignStatement ();
+                       assign.Left = new CodeVariableReferenceExpression ("Container");
+                       assign.Right = new CodeCastExpression (containerType,
+                                               new CodePropertyReferenceExpression (target, "BindingContainer"));
+                       method.Statements.Add (assign);
+
+                       CodeMethodInvokeExpression invoke = new CodeMethodInvokeExpression ();
+                       invoke.Method = new CodeMethodReferenceExpression (target, "SetDataBoundString");
+                       invoke.Parameters.Add (new CodePrimitiveExpression (0));
+                       CodeMethodInvokeExpression tostring = new CodeMethodInvokeExpression ();
+                       tostring.Method = new CodeMethodReferenceExpression (
+                                                       new CodeTypeReferenceExpression (typeof (Convert)),
+                                                       "ToString");
+                       tostring.Parameters.Add (new CodeSnippetExpression (db.Code));
+                       invoke.Parameters.Add (tostring);
+                       method.Statements.Add (invoke);
+                       
+                       mainClass.Members.Add (method);
+
+                       AddChildCall (builder, db);
+               }
+
+               void FlushText (ControlBuilder builder, StringBuilder sb)
+               {
+                       if (sb.Length > 0) {
+                               AddLiteralSubObject (builder, sb.ToString ());
+                               sb.Length = 0;
+                       }
+               }
+
+               void CreateControlTree (ControlBuilder builder, bool inTemplate, bool childrenAsProperties)
+               {
+                       EnsureID (builder);
+                       bool isTemplate = (typeof (TemplateBuilder).IsAssignableFrom (builder.GetType ()));
+                       if (!isTemplate)
+                               CreateField (builder, true);
+
+                       InitMethod (builder, isTemplate, childrenAsProperties || isTemplate);
+                       CreateAssignStatementsFromAttributes (builder);
+
+                       if (builder.Children != null && builder.Children.Count > 0) {
+                               ArrayList templates = null;
+
+                               StringBuilder sb = new StringBuilder ();
+                               foreach (object b in builder.Children) {
+
+                                       if (b is string) {
+                                               sb.Append ((string) b);
+                                               continue;
+                                       }
+
+                                       FlushText (builder, sb);
+                                       if (b is ObjectTagBuilder) {
+                                               ProcessObjectTag ((ObjectTagBuilder) b);
+                                               continue;
+                                       }
+
+                                       if (b is TemplateBuilder) {
+                                               if (templates == null)
+                                                       templates = new ArrayList ();
+
+                                               templates.Add (b);
+                                               continue;
+                                       }
+
+                                       if (b is CodeRenderBuilder) {
+                                               AddCodeRender (builder, (CodeRenderBuilder) b);
+                                               continue;
+                                       }
+
+                                       if (b is DataBindingBuilder) {
+                                               AddDataBindingLiteral (builder, (DataBindingBuilder) b);
+                                               continue;
+                                       }
+
+                                       if (b is ControlBuilder) {
+                                               ControlBuilder child = (ControlBuilder) b;
+                                               CreateControlTree (child, inTemplate, builder.FChildrenAsProperties);
+                                               AddChildCall (builder, child);
+                                               continue;
+                                       }
+
+                                       throw new Exception ("???");
+                               }
+
+                               FlushText (builder, sb);
+
+                               if (templates != null) {
+                                       foreach (ControlBuilder b in templates) {
+                                               CreateControlTree (b, true, false);
+                                               AddTemplateInvocation (builder.method, b.TagName, b.method.Name);
+                                       }
+                               }
+
+                       }
+
+                       if (builder.defaultPropertyBuilder != null) {
+                               ControlBuilder b = builder.defaultPropertyBuilder;
+                               CreateControlTree (b, false, true);
+                               Console.WriteLine ("Aqui");
+                               AddChildCall (builder, b);
+                       }
+
+                       if (builder.HasAspCode) {
+                               CodeMethodReferenceExpression m = new CodeMethodReferenceExpression ();
+                               m.TargetObject = thisRef;
+                               m.MethodName = builder.renderMethod.Name;
+
+                               CodeObjectCreateExpression create = new CodeObjectCreateExpression ();
+                               create.CreateType = new CodeTypeReference (typeof (RenderMethod));
+                               create.Parameters.Add (m);
+
+                               CodeMethodInvokeExpression invoke = new CodeMethodInvokeExpression ();
+                               invoke.Method = new CodeMethodReferenceExpression (ctrlVar, "SetRenderMethodDelegate");
+                               invoke.Parameters.Add (create);
+
+                               builder.method.Statements.Add (invoke);
+                       }
+                       
+                       if (typeof (Control).IsAssignableFrom (builder.ControlType))
+                               builder.method.Statements.Add (new CodeMethodReturnStatement (ctrlVar));
+               }
+
+               protected override void CreateMethods ()
+               {
+                       base.CreateMethods ();
+
+                       CreateProperties ();
+                       CreateControlTree (parser.RootBuilder, false, false);
+                       CreateFrameworkInitializeMethod ();
+               }
+               
+               void CreateFrameworkInitializeMethod ()
+               {
+                       CodeMemberMethod method = new CodeMemberMethod ();
+                       method.Name = "FrameworkInitialize";
+                       method.Attributes = MemberAttributes.Family | MemberAttributes.Override;
+                       AddStatementsToFrameworkInitialize (method);
+                       mainClass.Members.Add (method);
+               }
+
+               protected virtual void AddStatementsToFrameworkInitialize (CodeMemberMethod method)
+               {
+                       if (!parser.EnableViewState) {
+                               CodeAssignStatement stmt = new CodeAssignStatement ();
+                               stmt.Left = new CodePropertyReferenceExpression (thisRef, "EnableViewState");
+                               stmt.Right = new CodePrimitiveExpression (false);
+                               method.Statements.Add (stmt);
+                       }
+
+                       CodeMethodReferenceExpression methodExpr;
+                       methodExpr = new CodeMethodReferenceExpression (thisRef, "__BuildControlTree");
+                       CodeMethodInvokeExpression expr = new CodeMethodInvokeExpression (methodExpr, thisRef);
+                       method.Statements.Add (new CodeExpressionStatement (expr));
+               }
+
+               protected override void ProcessObjectTag (ObjectTagBuilder tag)
+               {
+                       string name = tag.ObjectID;
+                       string className = tag.ClassName;
+                       Type t = null;
+                       try {
+                               t = parser.LoadType (className);
+                       } catch (Exception e) {
+                               throw new ParseException (tag.location, "Error loading type " + className);
+                       }
+
+                       string fieldName = "cached" + name;
+                       CodeMemberField f = new CodeMemberField (t, fieldName);
+                       f.Attributes = MemberAttributes.Private;
+                       mainClass.Members.Add (f);
+
+                       CodeFieldReferenceExpression field = new CodeFieldReferenceExpression (thisRef, fieldName);
+
+                       CodeMemberProperty prop = new CodeMemberProperty ();
+                       prop.Type = new CodeTypeReference (t);
+                       prop.Name = name;
+                       prop.Attributes = MemberAttributes.Private | MemberAttributes.Final;
+
+                       CodeConditionStatement stmt = new CodeConditionStatement();
+                       stmt.Condition = new CodeBinaryOperatorExpression (field,
+                                                                          CodeBinaryOperatorType.IdentityEquality,
+                                                                          new CodePrimitiveExpression (null));
+
+                       CodeObjectCreateExpression create = new CodeObjectCreateExpression (prop.Type); 
+                       stmt.TrueStatements.Add (new CodeAssignStatement (field, create));
+                       prop.GetStatements.Add (stmt);
+                       prop.GetStatements.Add (new CodeMethodReturnStatement (field));
+                       mainClass.Members.Add (prop);
+               }
+
+               void CreateProperties ()
+               {
+                       if (!parser.AutoEventWireup) {
+                               CreateAutoEventWireup ();
+                       } else {
+                               CreateAutoHandlers ();
+                       }
+
+                       CreateApplicationInstance ();
+                       CreateTemplateSourceDirectory ();
+               }
+
+               void CreateTemplateSourceDirectory ()
+               {
+                       CodeMemberProperty prop = new CodeMemberProperty ();
+                       prop.Type = new CodeTypeReference (typeof (string));
+                       prop.Name = "TemplateSourceDirectory";
+                       prop.Attributes = MemberAttributes.Public | MemberAttributes.Override;
+
+                       CodePrimitiveExpression expr = new CodePrimitiveExpression (parser.CurrentVirtualPath);
+                       prop.GetStatements.Add (new CodeMethodReturnStatement (expr));
+                       mainClass.Members.Add (prop);
+               }
+
+               void CreateApplicationInstance ()
+               {
+                       CodeMemberProperty prop = new CodeMemberProperty ();
+                       Type appType = typeof (HttpApplication);//FIXME: uncomment HttpApplicationFactory.AppType;
+                       prop.Type = new CodeTypeReference (appType);
+                       prop.Name = "ApplicationInstance";
+                       prop.Attributes = MemberAttributes.Family | MemberAttributes.Final;
+
+                       CodePropertyReferenceExpression propRef = new CodePropertyReferenceExpression (thisRef, "Context");
+
+                       propRef = new CodePropertyReferenceExpression (propRef, "ApplicationInstance");
+
+                       CodeCastExpression cast = new CodeCastExpression (appType.FullName, propRef);
+                       prop.GetStatements.Add (new CodeMethodReturnStatement (cast));
+                       mainClass.Members.Add (prop);
+               }
+
+               void CreateAutoHandlers ()
+               {
+                       // Create AutoHandlers property
+                       CodeMemberProperty prop = new CodeMemberProperty ();
+                       prop.Type = new CodeTypeReference (typeof (int));
+                       prop.Name = "AutoHandlers";
+                       prop.Attributes = MemberAttributes.Family | MemberAttributes.Override;
+                       
+                       CodeMethodReturnStatement ret = new CodeMethodReturnStatement ();
+                       CodeFieldReferenceExpression fldRef ;
+                       fldRef = new CodeFieldReferenceExpression (mainClassExpr, "__autoHandlers");
+                       ret.Expression = fldRef;
+                       prop.GetStatements.Add (ret);
+                       
+                       prop.SetStatements.Add (new CodeAssignStatement (fldRef, new CodePropertySetValueReferenceExpression ()));
+
+                       mainClass.Members.Add (prop);
+
+                       // Add the __autoHandlers field
+                       CodeMemberField fld = new CodeMemberField (typeof (int), "__autoHandlers");
+                       fld.Attributes = MemberAttributes.Private | MemberAttributes.Static;
+                       mainClass.Members.Add (fld);
+               }
+
+               void CreateAutoEventWireup ()
+               {
+                       // The getter returns false
+                       CodeMemberProperty prop = new CodeMemberProperty ();
+                       prop.Type = new CodeTypeReference (typeof (int));
+                       prop.Name = "AutoEventWireup";
+                       prop.Attributes = MemberAttributes.Family | MemberAttributes.Override;
+                       prop.GetStatements.Add (new CodeMethodReturnStatement (new CodePrimitiveExpression (false)));
+                       mainClass.Members.Add (prop);
+               }
+               
+               CodeExpression GetExpressionFromString (Type type, string str)
+               {
+                       if (type == typeof (string))
+                               return new CodePrimitiveExpression (str);
+
+                       if (type == typeof (bool)) {
+                               if (str == null || str == "" || 0 == String.Compare (str, "true", true))
+                                       return new CodePrimitiveExpression (true);
+                               else if (0 == String.Compare (str, "false", true))
+                                       return new CodePrimitiveExpression (false);
+                               else
+                                       throw new HttpException ("Value '" + str  + "' is not a valid boolean.");
+                       }
+
+                       if (str == null)
+                               return new CodePrimitiveExpression (null);
+
+                       if (type.IsPrimitive)
+                               return new CodePrimitiveExpression (Convert.ChangeType (str, type));
+
+                       if (type.IsEnum) {
+                               object val = null;
+                               try {
+                                       val = Enum.Parse (type, str, true);
+                               } catch (Exception) {
+                                       throw new HttpException (str + " is not a valid value for enum '" + type + "'");
+                               }
+                               CodeFieldReferenceExpression expr = new CodeFieldReferenceExpression ();
+                               expr.TargetObject = new CodeTypeReferenceExpression (type);
+                               expr.FieldName = val.ToString ();
+                               return expr;
+                       }
+
+                       if (type == typeof (Color)){
+                               if (colorConverter == null)
+                                       colorConverter = TypeDescriptor.GetConverter (typeof (Color));
+
+                               Color c;
+                               try {
+                                       c = (Color) colorConverter.ConvertFromString (str);
+                               } catch (Exception e){
+                                       throw new HttpException ("Color " + str + " is not a valid color.", e);
+                               }
+
+                               if (c.IsKnownColor){
+                                       CodeFieldReferenceExpression expr = new CodeFieldReferenceExpression ();
+                                       expr.TargetObject = new CodeTypeReferenceExpression (type);
+                                       expr.FieldName = c.Name;
+                                       return expr;
+                               } else {
+                                       CodeMethodReferenceExpression m = new CodeMethodReferenceExpression ();
+                                       m.TargetObject = new CodeTypeReferenceExpression (type);
+                                       m.MethodName = "FromArgb";
+                                       CodeMethodInvokeExpression invoke = new CodeMethodInvokeExpression (m);
+                                       invoke.Parameters.Add (new CodePrimitiveExpression (c.A));
+                                       invoke.Parameters.Add (new CodePrimitiveExpression (c.R));
+                                       invoke.Parameters.Add (new CodePrimitiveExpression (c.G));
+                                       invoke.Parameters.Add (new CodePrimitiveExpression (c.B));
+                                       return invoke;
+                               }
+                       }
+
+                       bool parms = false;
+                       BindingFlags flags = BindingFlags.Public | BindingFlags.Static;
+                       MethodInfo parse = type.GetMethod ("Parse", flags, null, arrayStringCultureInfo, null);
+                       if (parse != null) {
+                               parms = true;
+                       } else {
+                               parse = type.GetMethod ("Parse", flags, null, arrayString, null);
+                       }
+
+                       if (parse != null) {
+                               object o = null;
+                               try {
+                                       if (parms)
+                                               o = parse.Invoke (null, new object [] { str, CultureInfo.InvariantCulture });
+                                       else
+                                               o = parse.Invoke (null, new object [] { str });
+                               } catch (Exception e) {
+                                       throw new HttpException ("Cannot parse " + str + " as " + type, e);
+                               }
+                               
+                               if (o == null)
+                                       throw new HttpException (str + " as " + type + " is null");
+
+                               CodeTypeReferenceExpression exprType = new CodeTypeReferenceExpression (type);
+                               CodeMethodInvokeExpression invoke = new CodeMethodInvokeExpression (exprType, "Parse");
+                               //FIXME: may be we gotta ensure roundtrip between o.ToString and Parse
+                               invoke.Parameters.Add (new CodePrimitiveExpression (o.ToString ()));
+                               if (parms) {
+                                       CodeTypeReferenceExpression texp = new CodeTypeReferenceExpression (typeof (CultureInfo));
+                                       CodePropertyReferenceExpression pexp = new CodePropertyReferenceExpression ();
+                                       pexp.TargetObject = texp;
+                                       pexp.PropertyName = "InvariantCulture";
+                                       invoke.Parameters.Add (pexp);
+                               }
+                               return invoke;
+                       }
+                               
+                       // FIXME: Arrays (arrays of string are implemented in old AspGenerator.cs
+                       Console.WriteLine ("Unknown type: " + type + " value: " + str);
+
+                       return new CodePrimitiveExpression (str);
+               }
+       }
+}
+
index 0298bfd54db4f2e489e586164524b6e96c5ebe95..15f439c4400369cde56b4b3635d0c0c38161a8c2 100644 (file)
 // Authors:
 //     Gonzalo Paniagua Javier (gonzalo@ximian.com)
 //
-// (C) 2002 Ximian, Inc (http://www.ximian.com)
+// (C) 2002,2003 Ximian, Inc (http://www.ximian.com)
 //
 using System;
-using System.IO;
-using System.Reflection;
 using System.Web.UI;
-using System.Web.Util;
 
 namespace System.Web.Compilation
 {
-       class UserControlCompiler : BaseCompiler
+       class UserControlCompiler : TemplateControlCompiler
        {
-               UserControlParser userControlParser;
-               string sourceFile;
-               string targetFile;
+               UserControlParser parser;
 
-               internal UserControlCompiler (UserControlParser userControlParser)
+               public UserControlCompiler (UserControlParser parser)
+                       : base (parser)
                {
-                       this.userControlParser = userControlParser;
-               }
-
-               public override Type GetCompiledType ()
-               {
-                       string inputFile = userControlParser.InputFile;
-                       sourceFile = GenerateSourceFile (userControlParser);
-
-                       CachingCompiler compiler = new CachingCompiler (this);
-                       CompilationResult result = new CompilationResult (sourceFile);
-                       result.Options = options;
-                       if (compiler.Compile (result) == false)
-                               throw new CompilationException (result);
-                       
-                       result.Dependencies = dependencies;
-                       if (result.Data is Type) {
-                               targetFile = result.OutputFile;
-                               return (Type) result.Data;
-                       }
-
-                       Assembly assembly = Assembly.LoadFrom (result.OutputFile);
-                       Type [] types = assembly.GetTypes ();
-                       foreach (Type t in types) {
-                               if (t.IsSubclassOf (typeof (UserControl))) {
-                                       if (result.Data != null)
-                                               throw new CompilationException ("More that 1 user control!!!", result);
-                                       result.Data = t;
-                               }
-                       }
-
-                       return result.Data as Type;
-               }
-
-               public override string Key {
-                       get {
-                               return userControlParser.InputFile;
-                       }
-               }
-
-               public override string SourceFile {
-                       get {
-                               return sourceFile;
-                       }
-               }
-
-               public override string TargetFile {
-                       get {
-                               if (targetFile == null)
-                                       targetFile = Path.ChangeExtension (sourceFile, ".dll");
-
-                               return targetFile;
-                       }
+                       this.parser = parser;
                }
 
                public static Type CompileUserControlType (UserControlParser userControlParser)
                {
-                       CompilationCacheItem item = CachingCompiler.GetCached (userControlParser.InputFile);
-                       if (item != null && item.Result != null) {
-                               if (item.Result != null) {
-                                       userControlParser.Options = item.Result.Options;
-                                       return item.Result.Data as Type;
-                               }
-
-                               throw new CompilationException (item.Result);
-                       }
-
                        UserControlCompiler pc = new UserControlCompiler (userControlParser);
                        return pc.GetCompiledType ();
                }
-
-               string GenerateSourceFile (UserControlParser userControlParser)
-               {
-                       string inputFile = userControlParser.InputFile;
-
-                       AspGenerator generator = new AspGenerator (inputFile);
-                       generator.Context = userControlParser.Context;
-                       generator.BaseType = userControlParser.BaseType.ToString ();
-                       generator.ProcessElements ();
-                       userControlParser.Text = generator.GetCode ().ReadToEnd ();
-                       options = generator.Options;
-                       dependencies = generator.Dependencies;
-
-                       //FIXME: should get Tmp dir for this application
-                       string csName = Path.GetTempFileName () + ".cs";
-                       WebTrace.WriteLine ("Writing {0}", csName);
-                       StreamWriter output = new StreamWriter (File.OpenWrite (csName));
-                       output.Write (userControlParser.Text);
-                       output.Close ();
-                       return csName;
-               }
        }
 }
 
index 50e9962fb2fdceeb130008dcb30dc3a90a73db97..b414e78530aad46a64396fed4156fa516a682854 100644 (file)
@@ -4,11 +4,9 @@
 // Authors:
 //     Gonzalo Paniagua Javier (gonzalo@ximian.com)
 //
-// (C) 2002 Ximian, Inc (http://www.ximian.com)
+// (C) 2002,2003 Ximian, Inc (http://www.ximian.com)
 //
 using System;
-using System.IO;
-using System.Reflection;
 using System.Web.UI;
 
 namespace System.Web.Compilation
@@ -16,69 +14,18 @@ namespace System.Web.Compilation
        class WebServiceCompiler : BaseCompiler
        {
                SimpleWebHandlerParser wService;
-               string sourceFile;
 
-               private WebServiceCompiler (SimpleWebHandlerParser wService)
+               [MonoTODO]
+               public WebServiceCompiler (SimpleWebHandlerParser wService)
+                       : base (null)
                {
                        this.wService = wService;
                }
 
+               [MonoTODO]
                public static Type CompileIntoType (SimpleWebHandlerParser wService)
                {
-                       CompilationCacheItem item = CachingCompiler.GetCached (wService.PhysicalPath);
-                       if (item != null && item.Result != null) {
-                               if (item.Result != null)
-                                       return item.Result.Data as Type;
-
-                               throw new CompilationException (item.Result);
-                       }
-
-                       WebServiceCompiler wsc = new WebServiceCompiler (wService);
-                       return wsc.GetCompiledType ();
-               }
-
-               static string GenerateSourceFile (SimpleWebHandlerParser wService)
-               {
-                       //FIXME: should get Tmp dir for this application
-                       string csName = Path.GetTempFileName ();
-                       StreamWriter output = new StreamWriter (File.OpenWrite (csName));
-                       output.Write (wService.Program);
-                       output.Close ();
-                       return csName;
-               }
-
-               public override Type GetCompiledType ()
-               {
-                       sourceFile = GenerateSourceFile (wService);
-
-                       CachingCompiler compiler = new CachingCompiler (this);
-                       CompilationResult result = new CompilationResult ();
-                       if (compiler.Compile (result) == false)
-                               throw new CompilationException (result);
-                               
-                       Assembly assembly = Assembly.LoadFrom (result.OutputFile);
-                       Type [] types = assembly.GetTypes ();
-                       Type type = types [0];
-                       if (type.FullName != wService.ClassName)
-                               throw new ApplicationException (String.Format (
-                                                               "Class={0}, but the class compiled is {1}",
-                                                               wService.ClassName,
-                                                               type.FullName));
-                                                               
-                       result.Data = type;
-                       return type;
-               }
-
-               public override string Key {
-                       get {
-                               return wService.PhysicalPath;
-                       }
-               }
-
-               public override string SourceFile {
-                       get {
-                               return sourceFile;
-                       }
+                       return null;
                }
        }
 }