X-Git-Url: http://wien.tomnetworks.com/gitweb/?a=blobdiff_plain;ds=sidebyside;f=mcs%2Fclass%2FSystem.Web%2FSystem.Web.Compilation%2FAspGenerator.cs;h=3045ecc89647d9f878b833686a6d36aeb44bc686;hb=0add6b40f74432b122ded325ff36fa80fa024c84;hp=7fd78a6ff32b8c78366e2d4e7850f8a1cca3016f;hpb=3e90439160cf40cabb6683736c085747bcbbf272;p=mono.git diff --git a/mcs/class/System.Web/System.Web.Compilation/AspGenerator.cs b/mcs/class/System.Web/System.Web.Compilation/AspGenerator.cs index 7fd78a6ff32..3045ecc8964 100644 --- a/mcs/class/System.Web/System.Web.Compilation/AspGenerator.cs +++ b/mcs/class/System.Web/System.Web.Compilation/AspGenerator.cs @@ -4,1621 +4,529 @@ // 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; -using System.ComponentModel; -using System.Drawing; -using System.Diagnostics; +using System.CodeDom.Compiler; using System.IO; -using System.Reflection; using System.Text; -using System.Text.RegularExpressions; +using System.Web.Caching; 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 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 - container_type = type; - - return container_type; - } - - 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 void Pop () - { - controls.Pop (); - if (controls.Count != 0) - top = (ControlStackData) controls.Peek (); - sbt_valid = false; - } - - 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 - space_between_tags = false; - } - return space_between_tags; - } - } - - public Type Container - { - get { 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 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 () - { - return top.ToString () + " " + top.useCodeRender; - } - -} - -class ArrayListWrapper -{ - private ArrayList list; - private int index; - - public ArrayListWrapper (ArrayList list) + class ParserStack { - this.list = list; - index = -1; - } + Hashtable files; + Stack parsers; + AspParser current; - private void CheckIndex () - { - if (index == -1 || index == list.Count) - throw new InvalidOperationException (); - } - - public object Current - { - get { - CheckIndex (); - return list [index]; + public ParserStack () + { + files = new Hashtable (); // may be this should be case sensitive for windows + parsers = new Stack (); } + + public bool Push (AspParser parser) + { + if (files.Contains (parser.Filename)) + return false; - set { - CheckIndex (); - list [index] = value; + files [parser.Filename] = true; + parsers.Push (parser); + current = parser; + return true; } - } - public bool MoveNext () - { - if (index < list.Count) - index++; - - return index < list.Count; - } -} + public AspParser Pop () + { + if (parsers.Count == 0) + return null; -class AspGenerator -{ - private object [] parts; - private ArrayListWrapper elements; - private StringBuilder prolog; - private StringBuilder declarations; - private StringBuilder script; - private StringBuilder constructor; - private StringBuilder init_funcs; - private StringBuilder epilog; - private StringBuilder current_function; - private Stack functions; - private ControlStack controls; - private bool parse_ok; - private bool has_form_tag; - private AspComponentFoundry aspFoundry; - - private string classDecl; - private string className; - private string interfaces; - private string parent; - private string fullPath; - private static string enableSessionStateLiteral = ", System.Web.SessionState.IRequiresSessionState"; - - Hashtable options; - string privateBinPath; - - enum UserControlResult - { - OK = 0, - FileNotFound = 1, - CompilationFailed = 2 - } + files.Remove (current.Filename); + AspParser result = (AspParser) parsers.Pop (); + if (parsers.Count > 0) + current = (AspParser) parsers.Peek (); + else + current = null; - public AspGenerator (string pathToFile, ArrayList elements) - { - if (elements == null) - throw new ArgumentNullException (); - - this.elements = new ArrayListWrapper (elements); - 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 (IsUserControl) { - this.parent = "System.Web.UI.UserControl"; // Overriden by @ Control Inherits - this.interfaces = ""; - } else { - this.parent = "System.Web.UI.Page"; // Overriden by @ Page Inherits - this.interfaces = enableSessionStateLiteral; + return result; } - // - //*/ - this.has_form_tag = false; - AppDomainSetup setup = AppDomain.CurrentDomain.SetupInformation; - privateBinPath = setup.PrivateBinPath; - if (privateBinPath == null || privateBinPath.Length == 0) - privateBinPath = "bin"; - - if (!Path.IsPathRooted (privateBinPath)) - privateBinPath = Path.Combine (setup.ApplicationBase, privateBinPath); - Init (); - } - - public string BaseType - { - get { - return parent; - } - - set { - parent = value; + public AspParser Parser { + get { return current; } } - } - public bool IsUserControl - { - get { - return (BaseType == typeof (UserControl).ToString ()); + public string Filename { + get { return current.Filename; } } } - public string Interfaces - { - get { - return interfaces; + class AspGenerator + { + ParserStack pstack; + BuilderLocationStack stack; + TemplateParser tparser; + StringBuilder text; + RootBuilder rootBuilder; + bool inScript, javascript; + ILocation location; + static Hashtable emptyHash = new Hashtable (); + + public AspGenerator (TemplateParser tparser) + { + this.tparser = tparser; + tparser.AddDependency (tparser.InputFile); + text = new StringBuilder (); + stack = new BuilderLocationStack (); + rootBuilder = new RootBuilder (tparser); + stack.Push (rootBuilder, null); + tparser.RootBuilder = rootBuilder; + pstack = new ParserStack (); } - } - public Hashtable Options { - get { - if (options == null) - options = new Hashtable (); - - return options; + public AspParser Parser { + get { return pstack.Parser; } } - } - - public void AddInterface (string iface) - { - if (interfaces == "") { - interfaces = iface; - } else { - string s = ", " + iface; - if (interfaces.IndexOf (s) == -1) - interfaces += s; - } - } - - private AspComponentFoundry Foundry - { - get { - if (aspFoundry == null) - aspFoundry = new AspComponentFoundry (); - - return aspFoundry; + + public string Filename { + get { return pstack.Filename; } } - } - - private void Init () - { - 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 (); - - 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 StringReader GetCode () - { - if (!parse_ok) - throw new ApplicationException ("You gotta call ProcessElements () first!"); + + BaseCompiler GetCompilerFromType () + { + Type type = tparser.GetType (); + if (type == typeof (PageParser)) + return new PageCompiler ((PageParser) tparser); - StringBuilder code = new StringBuilder (); - for (int i = 0; i < parts.Length; i++) - code.Append ((StringBuilder) parts [i]); + if (type == typeof (ApplicationFileParser)) + return new GlobalAsaxCompiler ((ApplicationFileParser) tparser); - return new StringReader (code.ToString ()); - } + if (type == typeof (UserControlParser)) + return new UserControlCompiler ((UserControlParser) tparser); - public void Print () - { - if (!parse_ok){ - Console.WriteLine ("//Warning!!!: Elements not correctly parsed."); - } - - Console.Write (GetCode ().ReadToEnd ()); - } - - // Regex.Escape () make some illegal escape sequences for a C# source. - private string Escape (string input) - { - 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; - } - - private void PageDirective (TagAttributes att) - { - if (att ["ClassName"] != null){ - this.className = (string) att ["ClassName"]; - Options ["ClassName"] = className; + throw new Exception ("Got type: " + type); } + + void InitParser (string filename) + { + StreamReader reader = new StreamReader (filename, WebEncoding.FileEncoding); + AspParser parser = new AspParser (filename, reader); + reader.Close (); + parser.Error += new ParseErrorHandler (ParseError); + parser.TagParsed += new TagParsedHandler (TagParsed); + parser.TextParsed += new TextParsedHandler (TextParsed); + if (!pstack.Push (parser)) + throw new ParseException (Location, "Infinite recursion detected including file: " + filename); + tparser.AddDependency (filename); + } + + void DoParse () + { + pstack.Parser.Parse (); + if (text.Length > 0) + FlushText (); - if (att ["EnableSessionState"] != null){ - string est = (string) att ["EnableSessionState"]; - if (0 == String.Compare (est, "false", true)) - interfaces = interfaces.Replace (enableSessionStateLiteral, ""); - else if (0 != String.Compare (est, "true", true)) - throw new ApplicationException ("EnableSessionState in Page directive not set to " + - "a correct value: " + est); + pstack.Pop (); } - /* - if (att ["Inherits"] != null){ - parent = (string) att ["Inherits"]; - string source_file = att ["Src"] as string; - if (source_file != null) - buildOptions.AppendFormat ("//\n", source_file); - else - buildOptions.AppendFormat ("//\n", parent); + public Type GetCompiledType () + { + Type type = (Type) HttpRuntime.Cache.Get (tparser.InputFile); + if (type != null) { + return type; + } - } - */ + InitParser (Path.GetFullPath (tparser.InputFile)); + DoParse (); +#if DEBUG + PrintTree (rootBuilder, 0); +#endif - if (att ["CompilerOptions"] != null) - Options ["CompilerOptions"] = (string) att ["CompilerOptions"]; + if (stack.Count > 1) + throw new ParseException (stack.Builder.location, + "Expecting " + stack.Builder); - //FIXME: add support for more attributes. - } + BaseCompiler compiler = GetCompilerFromType (); - void AddReference (string dll) - { - string references = Options ["References"] as string; - if (references == null) - references = dll; - else - references = references + " " + dll; + type = compiler.GetCompiledType (); + CacheDependency cd = new CacheDependency ((string[]) + tparser.Dependencies.ToArray (typeof (string))); - 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 ()); - prolog.AppendFormat ("\tusing {0};\n", name_space); - string dll = privateBinPath + Path.DirectorySeparatorChar + assembly_name + ".dll"; - Foundry.RegisterFoundry (tag_prefix, dll, name_space); - AddReference (dll); - return; + HttpRuntime.Cache.Insert (tparser.InputFile, type, cd); + return type; } - if (tag_prefix != "" && tag_name != "" && src != ""){ - if (name_space != "" && assembly_name != "") - throw new ApplicationException ("Invalid attributes for @ Register: " + - att.ToString ()); - - if (!src.EndsWith (".ascx")) - throw new ApplicationException ("Source file extension for controls " + - "must be .ascx"); - - string pathToFile = Path.GetDirectoryName (src); - if (pathToFile == "") { - pathToFile = Path.GetDirectoryName (fullPath); - } else if (!Path.IsPathRooted (pathToFile)) { - pathToFile = Path.Combine (Path.GetDirectoryName (fullPath), pathToFile); - } - - string srcLocation = pathToFile + Path.DirectorySeparatorChar + Path.GetFileName (src); - UserControlData data = GenerateUserControl (srcLocation); - switch (data.result) { - case UserControlResult.OK: - prolog.AppendFormat ("\tusing {0};\n", "ASP"); - string dll = "output" + Path.DirectorySeparatorChar + data.assemblyName + ".dll"; - Foundry.RegisterFoundry (tag_prefix, 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; - } +#if DEBUG + static void PrintTree (ControlBuilder builder, int indent) + { + if (builder == null) + return; - throw new ApplicationException ("Invalid combination of attributes in " + - "@ Register: " + att.ToString ()); - } + string i = new string ('\t', indent); + Console.Write (i); + Console.WriteLine ("b: {0} id: {1} type: {2} parent: {3}", + builder, builder.ID, builder.ControlType, builder.parentBuilder); - private void ProcessDirective () - { - Directive directive = (Directive) elements.Current; - TagAttributes att = directive.Attributes; - if (att == null) - return; - - string id = directive.TagID.ToUpper (); - switch (id){ - case "PAGE": - case "CONTROL": - if (IsUserControl && id != "CONTROL") - throw new ApplicationException ("@Page not allowed if --control specified."); - else if (!IsUserControl && id != "PAGE") - throw new ApplicationException ("@Control not allowed here."); - PageDirective (att); - break; - case "IMPORT": - foreach (string key in att.Keys){ - if (0 == String.Compare (key, "NAMESPACE", true)){ - string _using = "using " + (string) att [key] + ";"; - if (prolog.ToString ().IndexOf (_using) == -1) - prolog.AppendFormat ("\tusing {0};\n", (string) att [key]); - break; - } + if (builder.Children != null) + foreach (object o in builder.Children) { + if (o is ControlBuilder) + PrintTree ((ControlBuilder) o, indent++); } - break; - case "IMPLEMENTS": - string iface = (string) att ["interface"]; - interfaces += ", " + iface; - break; - case "REGISTER": - RegisterDirective (att); - break; - } - } - - private void ProcessPlainText () - { - PlainText asis = (PlainText) elements.Current; - string trimmed = asis.Text.Trim (); - if (trimmed == "" && controls.SpaceBetweenTags == true) - return; - - if (trimmed != "" && controls.PeekChildKind () != ChildrenKind.CONTROLS){ - string tag_id = controls.PeekTagID (); - throw new ApplicationException ("Literal content not allowed for " + tag_id); } +#endif - 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); - - 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 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); + 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 (); } - if (prev_children_kind == ChildrenKind.DBCOLUMNS && - control_type != typeof (System.Web.UI.WebControls.DataGridColumn) && - !control_type.IsSubclassOf (typeof (System.Web.UI.WebControls.DataGridColumn))) - throw new ApplicationException ("Inside " + controls.PeekTagID () + " only " + - "System.Web.UI.WebControls.DataGridColum " + - "objects are allowed"); - else if (prev_children_kind == ChildrenKind.LISTITEM && - control_type != typeof (System.Web.UI.WebControls.ListItem)) - throw new ApplicationException ("Inside " + controls.PeekTagID () + " only " + - "System.Web.UI.WebControls.ListItem " + - "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; + void ParseError (ILocation location, string message) + { + throw new ParseException (location, message); } - 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)) - 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 (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 (string varName, string value) - { - if (value == "") - throw new ApplicationException ("Empty data binding tag."); - - string control_id = controls.PeekControlID (); - string control_type_string = controls.PeekType ().ToString (); - StringBuilder db_function = controls.DataBindFunction; - string container = "System.Web.UI.Control"; - 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 (); - - db_function.AppendFormat ("\t\t\ttarget.{0} = System.Convert.ToString ({1});\n", - varName, real_value); - } + void TagParsed (ILocation location, TagType tagtype, string tagid, TagAttributes attributes) + { + this.location = new Location (location); + if (tparser != null) + tparser.Location = location; - /* - * Returns true if it generates some code for the specified property - */ - private void AddPropertyCode (Type prop_type, string var_name, string att, bool isDataBound) - { - /* FIXME: should i check for this or let the compiler fail? - * if (!prop.CanWrite) - * .... - */ - if (prop_type == typeof (string)){ - if (att == null) - throw new ApplicationException ("null value for attribute " + var_name ); - - if (isDataBound) - DataBoundProperty (var_name, att); - else - current_function.AppendFormat ("\t\t\t__ctrl.{0} = \"{1}\";\n", var_name, - Escape (att)); // FIXME: really Escape this? - - } - else if (prop_type.IsEnum){ - if (att == null) - throw new ApplicationException ("null value for attribute " + var_name ); - - string enum_value = EnumValueNameToString (prop_type, att); - - current_function.AppendFormat ("\t\t\t__ctrl.{0} = {1};\n", var_name, enum_value); - } - else if (prop_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."); + if (text.Length != 0) + FlushText (); - current_function.AppendFormat ("\t\t\t__ctrl.{0} = {1};\n", var_name, value); - } - else if (prop_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."); + if (0 == String.Compare (tagid, "script", true)) { + if (ProcessScript (tagtype, attributes)) + return; } - 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 (prop_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."); + + switch (tagtype) { + case TagType.Directive: + if (tagid == "") + tagid = tparser.DefaultDirectiveName; + + 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); + } + break; + case TagType.DataBinding: + goto case TagType.CodeRender; + case TagType.CodeRenderExpression: + goto case TagType.CodeRender; + case TagType.CodeRender: + ProcessCode (tagtype, tagid, location); + break; + case TagType.Include: + string file = attributes ["virtual"] as string; + bool isvirtual = (file != null); + if (!isvirtual) + file = attributes ["file"] as string; + + if (isvirtual) { + file = tparser.MapPath (file); + } else if (!Path.IsPathRooted (file)) { + file = UrlUtils.Combine (tparser.BaseVirtualDir, file); + } + + InitParser (file); + DoParse (); + break; + default: + break; } - current_function.AppendFormat ("\t\t\t__ctrl.{0} = " + - "System.Web.UI.WebControls.FontUnit.Parse (\"{1}\", " + - "System.Globalization.CultureInfo.InvariantCulture);\n", - var_name, att); + //PrintLocation (location); } - else if (prop_type == typeof (Int16) || - prop_type == typeof (Int32) || - prop_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 (prop_type == typeof (UInt16) || - prop_type == typeof (UInt32) || - prop_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."); + void TextParsed (ILocation location, string text) + { + if (text.IndexOf ("<%") != -1 && !inScript) { + if (this.text.Length > 0) + FlushText (); + CodeRenderParser r = new CodeRenderParser (text, stack.Builder); + r.AddChildren (); + return; } - current_function.AppendFormat ("\t\t\t__ctrl.{0} = {1};\n", var_name, value); + this.text.Append (text); + //PrintLocation (location); } - else if (prop_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 (prop_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."); + void FlushText () + { + string t = text.ToString (); + text.Length = 0; + if (inScript) { + // TODO: store location + tparser.Scripts.Add (t); + return; } - current_function.AppendFormat ("\t\t\t__ctrl.{0} = {1};\n", var_name, value); - } - else if (prop_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); - } + if (tparser.DefaultDirectiveName == "application" && t.Trim () != "") + throw new ParseException (location, "Content not valid for application file."); - // 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 { - throw new ApplicationException ("Unsupported type in property: " + - prop_type.ToString ()); + stack.Builder.AppendLiteralString (t); } - } - private bool ProcessProperties (PropertyInfo prop, string id, TagAttributes att) - { - int hyphen = id.IndexOf ('-'); - - if (hyphen == -1 && prop.CanWrite == false) - return false; - - bool is_processed = false; - bool isDataBound = att.IsDataBound ((string) att [id]); - Type type = prop.PropertyType; - Type style = typeof (System.Web.UI.WebControls.Style); - Type fontinfo = typeof (System.Web.UI.WebControls.FontInfo); - - if (0 == String.Compare (prop.Name, id, true)){ - AddPropertyCode (type, prop.Name, (string) att [id], isDataBound); - is_processed = true; - } else if ((type == fontinfo || type == style || type.IsSubclassOf (style)) && hyphen != -1){ - string prop_field = id.Replace ("-", "."); - string [] parts = prop_field.Split (new char [] {'.'}); - if (parts.Length != 2 || 0 != String.Compare (prop.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; + bool ProcessTag (string tagid, TagAttributes atts) + { + if ((atts == null || !atts.IsRunAtServer ()) && String.Compare (tagid, "tbody", true) == 0) { + // MS completely ignores tbody or, if runat="server", fails when compiling + if (stack.Count > 0) + return stack.Builder.ChildrenAsProperties; - if (subprop.CanWrite == false) - return false; + return false; + } - bool is_bool = subprop.PropertyType == typeof (bool); - if (!is_bool && att == null){ - att [id] = ""; // Font-Size -> Font-Size="" as html - return false; + ControlBuilder parent = stack.Builder; + ControlBuilder builder = null; + BuilderLocation bl = null; + Hashtable htable = (atts != null) ? atts.GetDictionary (null) : emptyHash; + if (stack.Count > 1) { + try { + builder = parent.CreateSubBuilder (tagid, htable, null, tparser, location); + } catch (TypeLoadException e) { + throw new ParseException (Location, "Type not found.", e); + } catch (Exception e) { + throw new ParseException (Location, e.Message, e); } - - string value; - if (att == null && is_bool) - value = "true"; // Font-Bold <=> Font-Bold="true" - else - value = (string) att [id]; - - AddPropertyCode (subprop.PropertyType, - prop.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 (); - 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; + if (builder == null && atts != null && atts.IsRunAtServer ()) { + string id = htable ["id"] as string; + if (id != null && !CodeGenerator.IsValidLanguageIndependentIdentifier (id)) + throw new ParseException (Location, "'" + id + "' is not a valid identifier"); + + try { + builder = rootBuilder.CreateSubBuilder (tagid, htable, null, tparser, location); + } catch (TypeLoadException e) { + throw new ParseException (Location, "Type not found.", e); + } catch (Exception e) { + throw new ParseException (Location, e.Message, e); } - } - - foreach (PropertyInfo prop in prop_info){ - is_processed = ProcessProperties (prop, id, att); - if (is_processed) - break; } + + if (builder == null) + return false; - if (is_processed){ - is_processed = false; - continue; + builder.location = location; + builder.ID = htable ["id"] as string; + if (builder.HasBody ()) { + if (builder is TemplateBuilder) { + // push the id list + } + stack.Push (builder, location); + } else { + // FIXME:ObjectTags... + parent.AppendSubBuilder (builder); + builder.CloseControl (); } - current_function.AppendFormat ("\t\t\t((System.Web.UI.IAttributeAccessor) __ctrl)." + - "SetAttribute (\"{0}\", \"{1}\");\n", - id, Escape ((string) att [id])); + return true; } - } - - 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; - - StringBuilder old_function = (StringBuilder) functions.Pop (); - current_function = (StringBuilder) functions.Peek (); - - string control_id = controls.PeekControlID (); - Type control_type = controls.PeekType (); - - 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"; - if (controls.Container == typeof (System.Web.UI.HtmlControls.HtmlSelect)){ - parsed = "ParsedSubObject"; - ctrl_name = "parser"; + bool ProcessScript (TagType tagtype, TagAttributes attributes) + { + if (tagtype != TagType.Close) { + if (attributes != null && attributes.IsRunAtServer ()) { + CheckLanguage ((string) attributes ["language"]); + if (tagtype == TagType.Tag) { + Parser.VerbatimID = "script"; + inScript = true; + } //else if (tagtype == TagType.SelfClosing) + // load script file here + + return true; + } else { + Parser.VerbatimID = "script"; + javascript = true; + TextParsed (location, location.PlainText); + return true; + } } - 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 (controls.PeekChildKind () == 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 { - 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 ProcessHtmlControlTag () - { - HtmlControlTag html_ctrl = (HtmlControlTag) elements.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."); - - if (elements.MoveNext () == false) - throw new ApplicationException ("Error after " + html_ctrl.ToString ()); - - if (elements.Current is PlainText){ - script.Append (((PlainText) elements.Current).Text); - if (!elements.MoveNext ()) - throw new ApplicationException ("Error after " + - elements.Current.ToString ()); + bool result; + if (inScript) { + result = inScript; + inScript = false; + } else { + result = javascript; + javascript = false; + TextParsed (location, location.PlainText); } - if (elements.Current is CloseTag) - elements.MoveNext (); - return; + return result; } - - Type controlType = html_ctrl.ControlType; - declarations.AppendFormat ("\t\tprotected {0} {1};\n", controlType, html_ctrl.ControlID); - - ChildrenKind children_kind; - 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, null); - - current_function.AppendFormat ("\t\t\t__ctrl.ID = \"{0}\";\n", html_ctrl.ControlID); - - AddCodeForAttributes (html_ctrl.ControlType, html_ctrl.Attributes); - - if (!html_ctrl.SelfClosing) - JustDoIt (); - else - 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, - ChildrenKind.LISTITEM, - component.DefaultPropertyName); - - current_function = new StringBuilder (); - functions.Push (current_function); - current_function.AppendFormat ("\t\tprivate void __BuildControl_{0} " + - "(System.Web.UI.WebControls.ListItemCollection __ctrl)\n" + - "\t\t{{\n", control_id); - } - - private void ProcessComponent () - { - AspComponent component = (AspComponent) elements.Current; - Type component_type = component.ComponentType; - declarations.AppendFormat ("\t\tprotected {0} {1};\n", component_type, component.ControlID); - - NewControlFunction (component.TagID, component.ControlID, component_type, - component.ChildrenKind, component.DefaultPropertyName); - - if (component_type.IsSubclassOf (typeof (System.Web.UI.UserControl))) - current_function.Append ("\t\t\t__ctrl.InitializeAsUserControl (Page);\n"); - - if (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) - NewBuildListFunction (component); - - if (!component.SelfClosing) - JustDoIt (); - else - FinishControlFunction (component.TagID); - } - - private void ProcessServerObjectTag () - { - ServerObjectTag obj = (ServerObjectTag) elements.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 = ProcessProperties (subprop, id, att); - if (is_processed){ - subprop_name = subprop.Name; - break; + bool CloseControl (string tagid) + { + ControlBuilder current = stack.Builder; + if (String.Compare (tagid, "tbody", true) == 0) { + if (!current.ChildrenAsProperties) { + try { + TextParsed (location, location.PlainText); + FlushText (); + } catch {} } + return true; } + + string btag = current.TagName; + if (0 != String.Compare (tagid, btag, true)) + return false; - if (subprop_name == null) - throw new ApplicationException ("Property " + tag.TagID + " does not have " + - "a " + id + " subproperty."); + // if (current is TemplateBuilder) + // pop from the id list + current.CloseControl (); + stack.Pop (); + stack.Builder.AppendSubBuilder (current); + return true; } - // 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); - bool closing_tag_found = false; - Element elem; - while (!closing_tag_found && elements.MoveNext ()){ - elem = (Element) elements.Current; - if (elem is PlainText) - ProcessPlainText (); - else if (!(elem is CloseTag)) - throw new ApplicationException ("Tag " + tag.TagID + - " not properly closed."); - else - closing_tag_found = true; - } - - if (!closing_tag_found) - throw new ApplicationException ("Tag " + tag.TagID + " not properly closed."); + 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"); - controls.Pop (); + stack.Builder.AppendSubBuilder (b); + return true; } - } - - // 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.WebControl.DataGridColumnCollection __ctrl)\n" + - "\t\t{{\n", prop_id); - } - private void NewPropertyFunction (PropertyTag tag) - { - 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) elements.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