context: using System;
  using System.IO;
  using System.Linq;
  using System.Collections.Generic;
  using System.Reflection;
  using FxGqlLib;
  using System.Text;
  using System.Text.RegularExpressions;
  using System.Threading;
  using System.Diagnostics;
  using System.Globalization;
  
  namespace FxGqlC
  {
  	static class MainClass
  	{
  		static GqlEngine gqlEngine;
  		static string version;
  		static int versionType;
  		//static string lastRelease;
  		//static bool nochecknewversion = false;
  		//static bool noautoupdate = false;
  		static bool notracking = false;
  		//static DateTime lastCheck = DateTime.MinValue;
  		static bool continuePromptMode = true;
  		static bool verbose = false;
  		#if DEBUG
  		static bool breakOnException = false;
  		
  		#endif
  		static bool autoSize = false;
  		static int autoSizeRows = -1;
  		static int uniqueVisitorId = GetUniqueId ();
  		static int updatesBusy = 0;
  		static ManualResetEvent manualResetEvent = new ManualResetEvent (false);
  
  		[Flags]
  		enum ReportError
  		{
  			ApplicationExceptions = 0x1,
  			ExecutionExceptions = 0x2,
  			ParsingExceptions = 0x4,
  			NoConfirm = 0x8000,
  			None = 0,
  			All = 0x7fff,
  			Auto = ApplicationExceptions,
  		};
  
  		static ReportError reportError = ReportError.Auto;
  
  		enum OnOffEnum
  		{
  			Default = 0,
  			On = 1,
  			Off = 2,
  		}
  
  		static string GetVersion ()
  		{
              //var info = System.Diagnostics.FileVersionInfo.GetVersionInfo (Assembly.GetExecutingAssembly ().Location);
              //string type;
              //versionType = info.FileBuildPart;
              //switch (versionType) {
              //case 0:
              //	type = "alpha";
              //	break;
              //case 1:
              //	type = "beta";
              //	break;
              //case 2:
              //	type = "rc";
              //	break;
              //case 3:
              //	type = (info.FilePrivatePart == 0) ? null : "r";
              //	break;
              //default:
              //	type = "";
              //	break;
              //}
  
              //string version;
              //if (type != null)
              //	version = string.Format ("v{0}.{1}.{2}{3}", info.FileMajorPart, info.FileMinorPart, type, info.FilePrivatePart);
              //else
              //	version = string.Format ("v{0}.{1}", info.FileMajorPart, info.FileMinorPart);
  
              ////version += "-" + RetrieveLinkerTimestamp ().ToString ("yyyyMMdd");
  
              //return version;
  
              var attr = Attribute
                  .GetCustomAttributes(
                       Assembly.GetEntryAssembly(),
                       typeof(AssemblyInformationalVersionAttribute))
                  as AssemblyInformationalVersionAttribute[];
  
              string version;
              if (attr.Length > 0)
                  version = attr[0].InformationalVersion;
              else
                  version = "";
              return version;
          }
  
          [STAThread]
  		public static void Main (string[] args)
  		{
  			// Check for updates
  			version = GetVersion ();
  			CheckForUpdates (State.Start);
  
  			bool nologo = false;
  			bool help = false;
  			bool license = false;
  			bool prompt = false;
  			string command = null;
  			string gqlFile = null;
  			string logFile = "log.gql";
  			string autoexec = null;
  			List<string> errors = new List<string> ();
  			
  			for (int i = 0; i < args.Length; i++) {
  				if (string.Equals (args [i], "-nologo", StringComparison.InvariantCultureIgnoreCase))
  					nologo = true;
  				else if (string.Equals (args [i], "-help", StringComparison.InvariantCultureIgnoreCase)
  				         || string.Equals (args [i], "-h", StringComparison.InvariantCultureIgnoreCase))
  					help = true;
  				else if (string.Equals (args [i], "-license", StringComparison.InvariantCultureIgnoreCase))
  					license = true;
  				else if (string.Equals (args [i], "-prompt", StringComparison.InvariantCultureIgnoreCase)
  				         || string.Equals (args [i], "-p", StringComparison.InvariantCultureIgnoreCase))
  					prompt = true;
  				else if (string.Equals (args [i], "-command", StringComparison.InvariantCultureIgnoreCase)
  				         || string.Equals (args [i], "-c", StringComparison.InvariantCultureIgnoreCase)) {
  					i++;
  					if (i < args.Length)
  						command = args [i];
  					else
  						errors.Add ("Please specify a GQL command after '-command'");
  				} else if (string.Equals (args [i], "-gqlfile", StringComparison.InvariantCultureIgnoreCase)) {
  					i++;
  					if (i < args.Length)
  						gqlFile = args [i];
  					else
  						errors.Add ("Please specify a GQL file after '-gqlfile'");
  				} else if (string.Equals (args [i], "-logfile", StringComparison.InvariantCultureIgnoreCase)) {
  					if (i + 1 < args.Length && !args [i + 1].StartsWith ("-")) {
  						i++;
  						logFile = args [i];
  					} else {
  						logFile = null;
  					}
  				} else if (string.Equals (args [i], "-autoexec", StringComparison.InvariantCultureIgnoreCase)) {
  					i++;
  					if (i < args.Length)
  						autoexec = args [i];
  					else
  						errors.Add ("Please specify a GQL file after '-autoexec'");
  				//} else if (string.Equals (args [i], "-nochecknewversion", StringComparison.InvariantCultureIgnoreCase)) {
  				//	nochecknewversion = true;
  				//	notracking = true;
  				//} else if (string.Equals (args [i], "-noautoupdate", StringComparison.InvariantCultureIgnoreCase)) {
  				//	noautoupdate = true;
  				} else {
  					errors.Add (string.Format ("Unknown parameter '{0}'", args [i]));
  				}				
  			}
  						
  			if (!nologo) {
  				string title = ((AssemblyTitleAttribute)Attribute.GetCustomAttribute (
  					               Assembly.GetExecutingAssembly (), typeof(AssemblyTitleAttribute), false))
  					.Title;
  				string description = ((AssemblyDescriptionAttribute)Attribute.GetCustomAttribute (
  					                     Assembly.GetExecutingAssembly (), typeof(AssemblyDescriptionAttribute), false))
  					.Description;
  				string copyright = ((AssemblyCopyrightAttribute)Attribute.GetCustomAttribute (
  					                   Assembly.GetExecutingAssembly (), typeof(AssemblyCopyrightAttribute), false))
  					.Copyright;
  
  				Console.WriteLine ();
  				Console.WriteLine ("{0} - {1} - {2}", title, version, description);
  				Console.WriteLine (copyright);
  
  				string clr = "CLR " + System.Environment.Version.ToString ();
  				string runtime = "?";
  				Type type = Type.GetType ("Mono.Runtime");
  				if (type != null) {                                          
  					MethodInfo displayName = type.GetMethod ("GetDisplayName", BindingFlags.NonPublic | BindingFlags.Static); 
  					if (displayName != null)
  						runtime = "Mono " + displayName.Invoke (null, null) + ", " + clr;
  				} else {
  					runtime = "Microsoft.NET " + clr;
  				}
  
  				Console.WriteLine ("Using Runtime: {0}", runtime);
  //					Environment.OSVersion,
  //					Environment.Is64BitProcess ? "64bit" : "32bit",
  //					Environment.Is64BitOperatingSystem ? "64bit" : "32bit",
  //					Environment.ProcessorCount);
  			}
  
  							
  			if (license) {
  				Console.WriteLine ("This program is free software: you can redistribute it and/or modify");
  				Console.WriteLine ("it under the terms of the GNU General Public License as published by");
  				Console.WriteLine ("the Free Software Foundation, either version 3 of the License, or");
  				Console.WriteLine ("any later version.");
  				Console.WriteLine ();
  				Console.WriteLine ("This program is distributed in the hope that it will be useful,");
  				Console.WriteLine ("but WITHOUT ANY WARRANTY; without even the implied warranty of");
  				Console.WriteLine ("MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the");
  				Console.WriteLine ("GNU General Public License for more details.");
  				Console.WriteLine ();
  				Console.WriteLine ("You should have received a copy of the GNU General Public License");
  				Console.WriteLine ("along with this program.  If not, see <http://www.gnu.org/licenses/>.");
  				Console.WriteLine ();
  				Console.WriteLine ("FxGqlC depends on (and/or contains redistributables of) these open source");
  				Console.WriteLine ("products:");
  				Console.WriteLine ("* SharpZipLib, GPLv2 license, Copyright 2001-2010 Mike Krueger, John Reilly.");
  				Console.WriteLine ("* Antlr v3, Antlr3 license (BSD), Copyright (c) 2010 Terence Parr.");
  				Console.WriteLine ("* Mono MCS getline.cs, MIT X11 / Apache License 2.0A,  Copyright 2008 Novell.");
  				Console.WriteLine ("* unRAR, Copyright Alexander Roshal. 'The unRAR sources cannot be used to");
  				Console.WriteLine ("  re-create the RAR compression algorithm, which is proprietary. Distribution");
  				Console.WriteLine ("  of modified unRAR sources in separate form or as a part of other software is");
  				Console.WriteLine ("  permitted, provided that it is clearly stated in the documentation and");
  				Console.WriteLine ("  source comments that the code may not be used to develop a RAR (WinRAR)");
  				Console.WriteLine ("  compatible archiver.'");
  				Console.WriteLine ("* JUnrar, GPL license, Copyright (c) 2007 innoSysTec (R) GmbH, Edmund Wagner.");
  				Console.WriteLine ("* SharpCompress, MsPL license, Copyright (c) Adam Hathcock.");
  				Console.WriteLine ();
  				Console.WriteLine ("Contact Information: Wim Devos, wimobiwan+fxgqlc AT gmail DOT com");
  				Console.WriteLine ("===========================================================================");
  				return;
  			} else if (!nologo) {
  				Console.WriteLine ("Distributed under GPLv3.  Run FxGqlC.exe -license for more information.");
  				Console.WriteLine ("===========================================================================");
  			}
  
  			if (help || errors.Count > 0) {
  				foreach (string error in errors) {
  					Console.WriteLine (error);
  				}
  					
  				ShowHelp ();
  				return;
  			}
  			
  			if (string.IsNullOrEmpty (gqlFile)) {
  				Console.TreatControlCAsInput = false;
  			}
  			
  			Console.CancelKeyPress += delegate(object sender, ConsoleCancelEventArgs e) {
  				if (e.SpecialKey == ConsoleSpecialKey.ControlC) {
  					//Console.WriteLine ("===== Ctrl-C signal received =====");
  					e.Cancel = true;
  					gqlEngine.Interrupt ();
  				}
  			};
  
  			using (gqlEngine = new GqlEngine ()) {
  				gqlEngine.OutputStream = Console.Out;
  				gqlEngine.LogFile = logFile;
  //				if (logFile != null) {
  //					try {
  //						//gqlEngine.LogStream = new StreamWriter (logFile, true);
  //					} catch (Exception x) {
  //						Console.WriteLine ("Unable to open logfile '{0}'.  Continuing without logfile.", logFile);
  //						Console.WriteLine (x.Message);
  //					}
  //				}
  
  				try {
  					if (autoexec != null) {
  						ExecuteFile (autoexec);
  					} else {
  						if (File.Exists ("autoexec.gql"))
  							ExecuteFile ("autoexec.gql");
  						else {
  							string path = Path.GetDirectoryName (new Uri (
  								              Assembly.GetAssembly (typeof(MainClass)).CodeBase).LocalPath
  							              );
  							if (File.Exists (Path.Combine (path, "autoexec.gql")))
  								ExecuteFile (Path.Combine (path, "autoexec.gql"));
  						}
  					}
  				} catch (Exception x) {
  					Console.WriteLine ("Failed to execute autoexec script: {0}", x.Message);
  					ReportException ("autoexec", x);
  				}
  
  				try {
  					if (prompt) {
  						RunPrompt ();
  					} else if (command != null) {
  						ExecuteCommand (command);
  					} else if (gqlFile != null) {
  						ExecuteFile (gqlFile);
  					} else {
  						ShowHelp ();
  					}
  				} finally {
  					if (gqlEngine.LogStream != null) {
  						gqlEngine.LogStream.Close ();
  						gqlEngine.LogStream.Dispose ();
  						gqlEngine.LogStream = null;
  					}
  				}			
  			}
  
  			CheckForUpdates (State.Stop);
  			manualResetEvent.WaitOne (500);
  		}
  
  		/*
  		static private DateTime RetrieveLinkerTimestamp ()
  		{
  			string filePath = System.Reflection.Assembly.GetCallingAssembly ().Location;
  			const int c_PeHeaderOffset = 60;
  			const int c_LinkerTimestampOffset = 8;
  			byte[] b = new byte[2048];
  			System.IO.Stream s = null;
  
  			try {
  				s = new System.IO.FileStream (filePath, System.IO.FileMode.Open, System.IO.FileAccess.Read);
  				s.Read (b, 0, 2048);
  			} finally {
  				if (s != null) {
  					s.Close ();
  				}
  			}
  
  			int i = System.BitConverter.ToInt32 (b, c_PeHeaderOffset);
  			int secondsSince1970 = System.BitConverter.ToInt32 (b, i + c_LinkerTimestampOffset);
  			DateTime dt = new DateTime (1970, 1, 1, 0, 0, 0);
  			dt = dt.AddSeconds (secondsSince1970);
  			dt = dt.AddHours (TimeZone.CurrentTimeZone.GetUtcOffset (dt).Hours);
  			return dt;
  		}
  		*/
  
  		public static void ShowHelp ()
  		{
  			Console.WriteLine ("FxGqlC.exe usage");
  			Console.WriteLine ("   -help or -h         Show this help");
  			Console.WriteLine ("   -license            Shows license information");
  			Console.WriteLine ("   -prompt or -p       Run in prompt mode");
  			Console.WriteLine ("   -command <command>  Run a single command (usefull when running FxGqlC in");
  			Console.WriteLine ("        or -c <cmd>         scripts)");
  			Console.WriteLine ("   -gqlfile <file>     Run the commands from a file");
  			Console.WriteLine ("   -logfile <file>     Outputs all GQL commands and query output to a file");
  			Console.WriteLine ("   -autoexec <file>    Runs this file instead of 'autoexec.gql' before");
  			Console.WriteLine ("                            running any other command or before command ");
  			Console.WriteLine ("                            prompt mode is started");
  			//Console.WriteLine ("   -loglevel <#>")
  			Console.WriteLine ("===========================================================================");
  		}
  
  		static string MakeRelative (string currentDirectory, string file)
  		{
  			Uri uriCurrentDirectory = new Uri (currentDirectory + "/");
  			Uri uriFile = new Uri (file);
  			return Uri.UnescapeDataString (uriCurrentDirectory.MakeRelativeUri (uriFile).ToString ());
  		}
  
  		public static void RunPrompt ()
  		{
  			Mono.Terminal.LineEditor lineEditor = new Mono.Terminal.LineEditor ("FxGqlC", 50);
  			lineEditor.CtrlOPressed += delegate(object sender, EventArgs args) {
  				try {
  					//var copy = Console.Error;
  					//Console.SetError (TextWriter.Null);
  					string currentDirectory = gqlEngine.GqlEngineState.CurrentDirectory;
  					string[] files = FxGqlCWin.FileSelector.SelectMultipleFileRead ("Select filename(s) to inject in query string", currentDirectory);
  					//Console.SetError (copy);
  					if (files != null) {
  						StringBuilder sb = new StringBuilder ();
  						foreach (string file in files) {
  							string relativeFile = MakeRelative (currentDirectory, file);
  							if (sb.Length > 0)
  								sb.Append (", ");
  							sb.AppendFormat ("['{0}']", relativeFile);
  						}
  						lineEditor.Type (sb.ToString ());
  					}
  				} catch (Exception) {
  					// Ignore exceptions to prevent crash when DLL cannot be found.
  				}
  			};
  
  			while (continuePromptMode) {
  				string command = lineEditor.Edit ("FxGqlC> ", "");
  				//Console.Write ("FxGqlC> ");
  				//string command = Console.ReadLine ();
  				if (command.Trim ().Equals ("exit", StringComparison.InvariantCultureIgnoreCase)
  				    || command.Trim ().Equals ("quit", StringComparison.InvariantCultureIgnoreCase))
  					command = "!!exit"; 
  				if (!ExecutePromptCommand (command, lineEditor))
  				if (!ExecuteAliasCommand (command))
  					ExecuteCommand (command);
  			}
  			lineEditor.Close ();
  		}
  
  		static bool ExecutePromptCommand (string command, Mono.Terminal.LineEditor lineEditor)
  		{
  			command = command.Trim ();
  			if (command.StartsWith ("!!")) {
  				command = command.Substring (2).TrimStart ();
  				lineEditor.RemoveLast ();
  				switch (command.ToUpper ()) {
  				case "SHOWHISTORY":
  					lineEditor.ShowHistory ();
  					break;
  				case "EXIT":
  				case "QUIT":
  					continuePromptMode = false;
  					break;
  				default:
  					Console.WriteLine ("Unknown prompt command '{0}'", command);
  					break;
  				}
  				return true;
  			} else {
  				return false;
  			}
  		}
  
  		public static IEnumerable<string> SplitCommandLine (string commandLine)
  		{
  			bool inQuotes = false;
  
  			return commandLine.Split (c => {
  				if (c == '\"')
  					inQuotes = !inQuotes;
  
  				return !inQuotes && c == ' ';
  			}
  			)
                            .Select (arg => arg.Trim ().TrimMatchingQuotes ('\"'))
                            .Where (arg => !string.IsNullOrEmpty (arg));
  		}
  
  		static string EmptyToNull (string value)
  		{
  			return string.IsNullOrEmpty (value) ? null : value;
  		}
  
  		static string GetValue (string[] components, string id)
  		{
  			int id2 = int.Parse (id);
  			return id2 > 0 && id2 < components.Length ? EmptyToNull (components [id2]) : null;
  
  		}
  
  		static bool ExecuteAliasCommand (string command)
  		{
  			command = command.Trim ();
  			if (command.StartsWith ("@")) {
  				command = command.Substring (1).TrimStart ();
  				string[] components = SplitCommandLine (command).ToArray ();
  				string definition;
  				if (aliases.TryGetValue (components [0], out definition)) {
  					definition = Regex.Replace (definition, @"(?:\$\((?<id>\d+)(?:,(?<def>[^\)]+))?\))|(?:\$(?<id>\d+))", 
  						m => GetValue (components, m.Groups ["id"].Value) ?? EmptyToNull (m.Groups ["def"].Value) ?? "");
  					ExecuteCommand (definition);
  				} else {
  					Console.WriteLine ("Unknown command alias '{0}'", command);
  				}
  				return true;
  			} else {
  				return false;
  			}
  		}
  
  		public static void ExecuteCommand (string command)
  		{
  			if (!ExecuteClientCommand (command)) {
  				ExecuteServerCommand (command);
  			}
  			//CheckToDisplayNewVersionMessage ();
  		}
  
  		static bool ExecuteClientCommand (string command)
  		{
  			command = command.Trim ();
  			if (command.StartsWith ("!")) {
  				command = command.Substring (1).TrimStart ();
  				string[] commandComponents = command.Split (new char[] { ' ' }, 2, StringSplitOptions.RemoveEmptyEntries);
  
  				if (commandComponents.Length < 1) {
  					Console.WriteLine ("Invalid client command syntax");
  				} else {
  					switch (commandComponents [0].ToUpperInvariant ()) {
  					case "SET":
  						ExecuteClientCommandSet (commandComponents [1]);
  						break;
  					case "EXECUTE":
  						ExecuteClientCommandExecute (commandComponents [1]);
  						break;
  					case "ALIAS":
  						ExecuteClientCommandAlias (commandComponents [1]);
  						break;
  					default:
  						Console.WriteLine ("Unknown client command '{0}'", commandComponents [0]);
  						break;
  					}
  				}
  				return true;
  			} else {
  				return false;
  			}
  		}
  
  		private static void ExecuteServerCommandNative (string command)
  		{
  			gqlEngine.Execute (command);
  
  			foreach (Exception x in gqlEngine.GqlEngineState.Warnings) {
  				if (verbose) {
  					Console.WriteLine ("WARNING: {0}", x);
  				} else {
  					StringBuilder sb = new StringBuilder (x.Message);
  					Exception inner = x.InnerException;
  					while (inner != null) {
  						sb.Append (", ");
  						sb.Append (inner.Message);
  						inner = inner.InnerException;
  					}
  					Console.WriteLine ("WARNING: {0}", sb);
  				}
  				if (gqlEngine.LogStream != null)
  					gqlEngine.LogStream.WriteLine (x.ToString ());
  			}
  		}
  
  		public static void ExecuteServerCommand (string command)
  		{
  #if DEBUG
  			if (breakOnException) {
  				ExecuteServerCommandNative (command);
  			} else {
  #endif
  				try {
  					ExecuteServerCommandNative (command);
  				} catch (FxGqlLib.ParserException x) {
  					if (verbose)
  						Console.WriteLine (x);
  					else
  						Console.WriteLine (x.Message);
  					if (gqlEngine.LogStream != null)
  						gqlEngine.LogStream.WriteLine (x.ToString ());
  
  					string line;
  					using (StringReader stringReader = new System.IO.StringReader (command)) {
  						for (int no = 0; (line = stringReader.ReadLine ()) != null; no++) {
  							Console.WriteLine ("{0,3}: {1}", no + 1, line);
  							if (gqlEngine.LogStream != null)
  								gqlEngine.LogStream.WriteLine ("{0,3}: {1}", no + 1, line);
  							
  							if (no + 1 == x.Line) {
  								Console.WriteLine ("     {0}^", new string (' ', Math.Max (0, x.Pos)));
  								if (gqlEngine.LogStream != null)
  									gqlEngine.LogStream.WriteLine ("     {0}^", new string (' ', Math.Max (0, x.Pos)));
  							}
  						}
  					}
  					ReportException ("executing server command, " + command, x);
  				} catch (Exception x) {
  					if (verbose)
  						Console.WriteLine (x);
  					else
  						Console.WriteLine (x.Message);
  					if (gqlEngine.LogStream != null)
  						gqlEngine.LogStream.WriteLine (x.ToString ());
  					ReportException ("executing server command, " + command, x);
  				}
  #if DEBUG
  			}
  #endif
  		}
  
  		public static void ExecuteFile (string file)
  		{
  			using (StreamReader reader = new StreamReader (file)) {
  				string command = reader.ReadToEnd ();
  				ExecuteCommand (command);
  			}
  		}
  
  		static void ExecuteClientCommandSet (string command)
  		{
  			string[] commandComponents = command.Split (new char[] { ' ' }, 2, StringSplitOptions.RemoveEmptyEntries);
  			if (commandComponents.Length < 2) {
  				Console.WriteLine ("Invalid number of components in client command 'SET'");
  			} else {
  				string key = commandComponents [0];
  				string value = commandComponents [1];
  				switch (key.ToUpperInvariant ()) {
  				case "HEADING":
  					{
  						GqlEngineState.HeadingEnum heading;
  						if (Enum.TryParse<GqlEngineState.HeadingEnum> (value, true, out heading))
  							gqlEngine.GqlEngineState.Heading = heading;
  						else
  							Console.WriteLine ("Unknown SET HEADING value '{0}'", value);
  
  						break;
  					}
  				case "REPORTERROR":
  					{
  						ReportError reportError;
  						if (Enum.TryParse<ReportError> (value, true, out reportError))
  							MainClass.reportError = reportError;
  						else
  							Console.WriteLine ("Unknown SET REPORTERROR value '{0}'", value);
  
  						break;
  					}
  				case "VERBOSE":
  					{
  						OnOffEnum onOff;
  						if (Enum.TryParse<OnOffEnum> (value, true, out onOff))
  							verbose = (onOff == OnOffEnum.On);
  						else
  							Console.WriteLine ("Unknown SET VERBOSE value '{0}'", value);
  						break;
  					}
  #if _DEBUG
  				case "BREAKONEXCEPTION":
  					{
  						OnOffEnum onOff;
  						if (Enum.TryParse<OnOffEnum> (value, true, out onOff)) 
  							breakOnExeption = (onOff == OnOffEnum.On);
  						else
  							Console.WriteLine ("Unknown SET BREAKONEXCEPTION value '{0}'", value);
  						break;
  					}
  #endif
  				case "AUTOSIZE":
  					{
  						OnOffEnum onOff;
  						if (Enum.TryParse<OnOffEnum> (value, true, out onOff)) {
  							autoSize = (onOff == OnOffEnum.On);
  							if (autoSize)
  								gqlEngine.GqlEngineState.AutoSize = autoSizeRows;
  							else
  								gqlEngine.GqlEngineState.AutoSize = 0;
  						} else {
  							Console.WriteLine ("Unknown SET AUTOSIZE value '{0}'", value);
  						}
  						break;
  					}
  				case "AUTOSIZEROWS":
  					{
  						if (int.TryParse (value, out autoSizeRows)) {
  							if (autoSize)
  								gqlEngine.GqlEngineState.AutoSize = autoSizeRows;
  							else
  								gqlEngine.GqlEngineState.AutoSize = 0;
  						} else {
  							Console.WriteLine ("Unknown SET AUTOSIZEROWS value '{0}'", value);
  						}
  						break;
  					}
  				case "COLUMNDELIMITER":
  					if (value.Length >= 2 && value.StartsWith ("\'") && value.EndsWith ("\'"))
  						value = value.Substring (1, value.Length - 2);
  					gqlEngine.GqlEngineState.ColumnDelimiter = Regex.Unescape (value);
  					break;
  				case "CULTURE":
  					if (value.Length >= 2 && value.StartsWith ("\'") && value.EndsWith ("\'"))
  						value = value.Substring (1, value.Length - 2);
  					try {
  						CultureInfo cultureInfo = CultureInfo.GetCultureInfo (value);
  						gqlEngine.CultureInfo = cultureInfo;
  					} catch (Exception) {
  						Console.WriteLine ("Unknown SET CULTURE value '{0}'", value);
  					}
  					break;
  				case "CASEINSENSITIVE":
  					{
  						OnOffEnum onOff;
  						if (Enum.TryParse<OnOffEnum> (value, true, out onOff))
  							gqlEngine.CaseInsensitive = (onOff == OnOffEnum.On);
  						else
  							Console.WriteLine ("Unknown SET CASEINSENSITIVE value '{0}'", value);
  						break;
  					}
  				default:
  
gt: 					Console.WriteLine ("Unknown SET command '{0}'", key);