+
+#if NET_2_0
+ PageParserFilter PageParserFilter {
+ get {
+ if (tparser == null)
+ return null;
+
+ return tparser.PageParserFilter;
+ }
+ }
+
+ // KLUDGE WARNING
+ //
+ // The kludge to determine the base type of the to-be-generated ASP.NET class is
+ // very unfortunate but with our current parser it is, unfortunately, necessary. The
+ // reason for reading the entire file into memory and parsing it with a regexp is
+ // that we need to read the main directive (i.e. <%@Page %>, <%@Control %> etc),
+ // pass it to the page parser filter if it exists, and finally read the inherits
+ // attribute of the directive to get access to the base type of the class to be
+ // generated. On that type we check whether it is decorated with the
+ // FileLevelControlBuilder attribute and, if yes, use the indicated type as the
+ // RootBuilder. This is necessary for the ASP.NET MVC views using the "generic"
+ // inherits declaration to work properly. Our current parser is not able to parse
+ // the input file out of sequence (i.e. directives first, then the rest) so we need
+ // to do what we do below, alas.
+ Hashtable GetDirectiveAttributesDictionary (string skipKeyName, CaptureCollection names, CaptureCollection values)
+ {
+ var ret = new Hashtable (StringComparer.InvariantCultureIgnoreCase);
+
+ int index = 0;
+ string keyName;
+ foreach (Capture c in names) {
+ keyName = c.Value;
+ if (String.Compare (skipKeyName, keyName, StringComparison.OrdinalIgnoreCase) == 0) {
+ index++;
+ continue;
+ }
+
+ ret.Add (c.Value, values [index++].Value);
+ }
+
+ return ret;
+ }
+
+ string GetDirectiveName (CaptureCollection names)
+ {
+ string val;
+ foreach (Capture c in names) {
+ val = c.Value;
+ if (Directive.IsDirective (val))
+ return val;
+ }
+
+ return tparser.DefaultDirectiveName;
+ }
+
+ int GetLineNumberForIndex (string fileContents, int index)
+ {
+ int line = 1;
+ char c;
+ bool foundCR = false;
+
+ for (int pos = 0; pos < index; pos++) {
+ c = fileContents [pos];
+ if (c == '\n' || foundCR) {
+ line++;
+ foundCR = false;
+ }
+
+ foundCR = (c == '\r');
+ }
+
+ return line;
+ }
+
+ int GetNumberOfLinesForRange (string fileContents, int index, int length)
+ {
+ int lines = 0;
+ int stop = index + length;
+ char c;
+ bool foundCR = false;
+
+ for (int pos = index; pos < stop; pos++) {
+ c = fileContents [pos];
+ if (c == '\n' || foundCR) {
+ lines++;
+ foundCR = false;
+ }
+
+ foundCR = (c == '\r');
+ }
+
+ return lines;
+ }
+
+ Type GetInheritedType (string fileContents, string filename)
+ {
+ MatchCollection matches = DirectiveRegex.Matches (fileContents);
+ if (matches == null || matches.Count == 0)
+ return null;
+
+ string wantedDirectiveName = tparser.DefaultDirectiveName.ToLower ();
+ string directiveName;
+ GroupCollection groups;
+ CaptureCollection ccNames;
+
+ foreach (Match match in matches) {
+ groups = match.Groups;
+ if (groups.Count < 6)
+ continue;
+
+ ccNames = groups [3].Captures;
+ directiveName = GetDirectiveName (ccNames);
+ if (String.IsNullOrEmpty (directiveName))
+ continue;
+
+ if (String.Compare (directiveName.ToLower (), wantedDirectiveName, StringComparison.Ordinal) != 0)
+ continue;
+
+ var loc = new Location (null);
+ int index = match.Index;
+
+ loc.Filename = filename;
+ loc.BeginLine = GetLineNumberForIndex (fileContents, index);
+ loc.EndLine = loc.BeginLine + GetNumberOfLinesForRange (fileContents, index, match.Length);
+
+ tparser.Location = loc;
+ tparser.allowedMainDirectives = 2;
+ tparser.AddDirective (wantedDirectiveName, GetDirectiveAttributesDictionary (wantedDirectiveName, ccNames, groups [5].Captures));
+
+ return tparser.BaseType;
+ }
+
+ return null;
+ }
+
+ string ReadFileContents (Stream inputStream, string filename)
+ {
+ string ret = null;
+
+ if (inputStream != null) {
+ if (inputStream.CanSeek) {
+ long curPos = inputStream.Position;
+ inputStream.Seek (0, SeekOrigin.Begin);
+
+ Encoding enc = WebEncoding.FileEncoding;
+ StringBuilder sb = new StringBuilder ();
+ byte[] buffer = new byte [READ_BUFFER_SIZE];
+ int nbytes;
+
+ while ((nbytes = inputStream.Read (buffer, 0, READ_BUFFER_SIZE)) > 0)
+ sb.Append (enc.GetString (buffer, 0, nbytes));
+ inputStream.Seek (curPos, SeekOrigin.Begin);
+
+ ret = sb.ToString ();
+ sb.Length = 0;
+ sb.Capacity = 0;
+ } else {
+ FileStream fs = inputStream as FileStream;
+ if (fs != null) {
+ string fname = fs.Name;
+ try {
+ if (File.Exists (fname))
+ ret = File.ReadAllText (fname);
+ } catch {
+ // ignore
+ }
+ }
+ }
+ }
+
+ if (ret == null && !String.IsNullOrEmpty (filename) && String.Compare (filename, "@@inner_string@@", StringComparison.Ordinal) != 0) {
+ try {
+ if (File.Exists (filename))
+ ret = File.ReadAllText (filename);
+ } catch {
+ // ignore
+ }
+ }
+
+ return ret;
+ }
+
+ Type GetRootBuilderType (Stream inputStream, string filename)
+ {
+ Type ret = null;
+ string fileContents;
+
+ if (tparser != null)
+ fileContents = ReadFileContents (inputStream, filename);
+ else
+ fileContents = null;
+
+ if (!String.IsNullOrEmpty (fileContents)) {
+ Type inheritedType = GetInheritedType (fileContents, filename);
+ fileContents = null;
+ if (inheritedType != null) {
+ FileLevelControlBuilderAttribute attr;
+
+ try {
+ object[] attrs = inheritedType.GetCustomAttributes (typeof (FileLevelControlBuilderAttribute), true);
+ if (attrs != null && attrs.Length > 0)
+ attr = attrs [0] as FileLevelControlBuilderAttribute;
+ else
+ attr = null;
+ } catch {
+ attr = null;
+ }
+
+ ret = attr != null ? attr.BuilderType : null;
+ }
+ }
+
+ if (ret == null) {
+ if (tparser is PageParser)
+ return typeof (FileLevelPageControlBuilder);
+ else if (tparser is UserControlParser)
+ return typeof (FileLevelUserControlBuilder);
+ else
+ return typeof (RootBuilder);
+ } else
+ return ret;
+ }
+
+ void CreateRootBuilder (Stream inputStream, string filename)
+ {
+ if (rootBuilder != null)
+ return;
+
+ Type rootBuilderType = GetRootBuilderType (inputStream, filename);
+ rootBuilder = Activator.CreateInstance (rootBuilderType) as RootBuilder;
+ if (rootBuilder == null)
+ throw new HttpException ("Cannot create an instance of file-level control builder.");
+ rootBuilder.Init (tparser, null, null, null, null, null);
+ if (componentFoundry != null)
+ rootBuilder.Foundry = componentFoundry;
+
+ stack.Push (rootBuilder, null);
+ tparser.RootBuilder = rootBuilder;
+ }
+#endif