Esempio n. 1
0
		static void Main(string[] args)
		{

			var TargetAssembly = Assembly.LoadFile(Path.GetFullPath(args[0]));
			var TargetType = TargetAssembly.GetType(args[1], true);
			var TargetFile = args[2];

			using (var p = new ProtectiveFileStream(new FileInfo(TargetFile)))
			using (var s = new StreamWriter(p))
			using (var w = new CodeWriter(s))
			{
				p.NotModified +=
					delegate
					{
						Console.WriteLine("Not modified. " + TargetFile);
					};

				#region content
				s.BaseStream.SetLength(0);

				w.Statement("// The code was generated. Modifications will be lost if regenerated.");

				var source = from k in TargetType.GetMethods()
							 let CLA = k.GetCustomAttributes(typeof(APDUClassAttribute), false).Cast<APDUClassAttribute>().FirstOrDefault()
							 where CLA != null
							 let INS = k.GetCustomAttributes(typeof(APDUInstructionAttribute), false).Cast<APDUInstructionAttribute>().FirstOrDefault()
							 where INS != null
							 group new { k, CLA, INS } by CLA;


				if (TargetFile.EndsWith(".Dispatch.cs"))
				{
					Console.WriteLine("will create dispatcher... " + TargetType.Name);


					#region .Dispatch.cs for card
                    //w.Statement("using ScriptCoreLibJavaCard.javacard.framework;");
                    w.Statement("using " + typeof(Applet).Namespace + ";");

					w.PartialTypeBlock(TargetType, null,
						delegate
						{
							w.Statement("[System.Runtime.CompilerServices.CompilerGeneratedAttribute]");
							w.Block("internal bool Dispatch(APDU e)",
								delegate
								{
									w.Statement("var buffer = e.getBuffer();");
									w.Statement("var CLA = (byte)buffer[ISO7816Constants.OFFSET_CLA];");
									w.Statement("var INS = (byte)buffer[ISO7816Constants.OFFSET_INS];");

									w.Statement("var P1 = (byte)buffer[ISO7816Constants.OFFSET_P1];");
									w.Statement("var P2 = (byte)buffer[ISO7816Constants.OFFSET_P2];");
									w.Statement("var Pi8 = (short)(((P1 & 0xff) << 8) + (P2 & 0xff));");

									
									foreach (var k in source)
									{
										#region CLA
										w.Region("CLA " + k.Key.CLA.ToHexLiteral(),
											delegate
											{
												w.Block("if (CLA == " + k.Key.CLA.ToHexLiteral() + ")",
													delegate
													{
														var Instructions = k.Select((q, i) => new { q.k, q.CLA, INS = q.CLA.AutoAssignInstructions ? (byte)i : q.INS.INS }).OrderBy(ik => ik.INS).ToArray();

														foreach (var i in Instructions.GroupBy(ik => ik.INS))
														{
															#region INS

															w.Block("if (INS == " + i.Key.ToHexLiteral() + ")",
																delegate
																{
																	// default calling convention...
																	// could be extended

																	if (i.Count() == 1)
																	{
																		DispatcherInvoke(w, i.Single().k);

																		w.Statement("return true;");
																	}
																	else
																	{
																		// we shall distinguish instructions via
																		// byte P1, yay

																		foreach (var jj in
																			from j in i
																			let jpp = j.k.GetParameters()
																			where jpp.Length >= 1
																			let j_P1 = jpp[1]
																			where j_P1.ParameterType == typeof(byte)
																			where (j_P1.Attributes & ParameterAttributes.HasDefault) == ParameterAttributes.HasDefault
																			let j_P1_value = (byte)j_P1.DefaultValue
																			orderby j_P1_value
																			select new { P1 = j_P1_value, j.k, j.CLA, j.INS }
																			)
																		{

																			w.Block("if (P1 == " + jj.P1.ToHexLiteral() + ")",
																				delegate
																				{
																					DispatcherInvoke(w, jj.k);
																					w.Statement("return true;");
																				}
																			);

																		}

																		// maybe invoke the one without a default P1?
																		w.Statement("return false;");
																	}


																}
															);

															#endregion
														}


													}
												);
											}
										);
										#endregion

									}

									w.Statement("return false;");
								}
							);
						}
					);
					#endregion
				}
				else
				{
					Console.WriteLine("will create proxy... " + TargetType.Name);

					#region proxy for host
					//w.Statement("using ScriptCoreLib;");
					w.Statement("using System;");

					w.Block("namespace " + TargetType.Namespace,
						delegate
						{
							w.Statement("[System.Runtime.CompilerServices.CompilerGeneratedAttribute]");
							//w.Statement("[Script]");

							w.Block("public partial class " + TargetType.Name + "Proxy",
								delegate
								{
									#region LengthExpected
									w.Statement("public byte LengthExpected;");
									w.Statement("public bool IsLengthExpectedSpecified;");

									w.Statement("public delegate void ByteArrayAction(byte[] e);");
									w.Statement("public ByteArrayAction Tx;");
									w.Statement("public ByteArrayAction Rx;");

									w.Block("protected byte[] InternalTransmit(byte[] data)",
										delegate
										{
											w.Statement("if (Tx != null) Tx(data);");
											w.Statement("var r = this.Transmitter.Transmit(data);");
											w.Statement("if (Rx != null) Rx(r);");
											w.Statement("return r;");
										}
									);

									//w.Statement("[Script]");
									w.Block("class WithLengthExpected_IDisposable : IDisposable",
										delegate
										{
											w.Statement("byte __LengthExpected;");
											w.Statement("bool __IsLengthExpectedSpecified;");
											w.Statement(TargetType.Name + "Proxy context;");

											w.Block("public WithLengthExpected_IDisposable(" + TargetType.Name + "Proxy context, byte value)",
												delegate
												{
													w.Statement("__LengthExpected = context.LengthExpected;");
													w.Statement("__IsLengthExpectedSpecified = context.IsLengthExpectedSpecified;");

													w.Statement("context.LengthExpected = value;");
													w.Statement("context.IsLengthExpectedSpecified = true;");

													w.Statement("this.context = context;");
												}
											);

											w.Block("public void Dispose()",
												delegate
												{
													w.Statement("this.context.LengthExpected = __LengthExpected;");
													w.Statement("this.context.IsLengthExpectedSpecified = __IsLengthExpectedSpecified;");
												}
											);
										}
									);

									w.Block("public IDisposable WithLengthExpected(byte value)",
										delegate
										{
											w.Statement("return new WithLengthExpected_IDisposable(this, value);");
										}
									);
									#endregion

									#region Tokens
									foreach (var Token in source.SelectMany(k => k).SelectMany(k => new[] { k.INS.InputParameterType, k.INS.OutputParameterType }).Where(k => k != null).Distinct())
									{
										#region GetCleanName
										Func<MethodInfo, string> GetCleanName =
											m =>
											{
												var Prefix = Token.Name + "_";

												if (m.Name.StartsWith(Prefix))
													return m.Name.Substring(Prefix.Length);

												return m.Name;
											};
										#endregion

										//w.Statement("[Script]");
										w.Block("public partial class " + Token.Name,
											delegate
											{
												foreach (var enumerator in source.SelectMany(k => k).Where(k => k.INS.InputParameterType == Token && k.INS.OutputParameterType == Token))
												{
													//w.Statement("[Script]");
													w.Block("public partial class " + GetCleanName(enumerator.k) + "Enumerator",
														delegate
														{
															w.Statement("private readonly " + TargetType.Name + "Proxy Host;");

															w.Block("public " + GetCleanName(enumerator.k) + "Enumerator(" + TargetType.Name + "Proxy Host)",
																delegate
																{
																	w.Statement("this.Host = Host;");
																}
															);

															w.Block("public bool MoveNext()",
																delegate
																{
																	w.Statement("this.Current = " + Token.Name + "." + GetCleanName(enumerator.k) + "(this.Host, this.Current);");
																	w.Statement("return Current != null;");
																}
															);

															w.Block("public " + Token.Name + " Current",
																delegate
																{
																	w.Statement("get;");
																	w.Statement("private set;");
																}
															);
														}
													);

													//w.Statement("[Script]");
													w.Block("public partial class " + GetCleanName(enumerator.k) + "Enumerable",
														delegate
														{
															w.Statement("private readonly " + TargetType.Name + "Proxy Host;");

															w.Block("public " + GetCleanName(enumerator.k) + "Enumerable(" + TargetType.Name + "Proxy Host)",
																delegate
																{
																	w.Statement("this.Host = Host;");
																}
															);

															w.Block("public " + GetCleanName(enumerator.k) + "Enumerator GetEnumerator()",
																delegate
																{
																	w.Statement("return new " + GetCleanName(enumerator.k) + "Enumerator(this.Host);");
																}
															);

														}
													);
												}

												w.Statement("public " + TargetType.Name + "Proxy Host { get; set; }");
												w.Statement("public short Token { get; set; }");

												w.Block("public static implicit operator short(" + Token.Name + " e)",
													delegate
													{
														w.Statement("if (e == null) return -1;");
														w.Statement("return e.Token;");
													}
												);

												w.Block("static private " + Token.Name + " FromBytes(" + TargetType.Name + "Proxy host, byte[] data)",
													delegate
													{
														w.Statement("if (data.Length != 4) return null;");
														w.Statement("if (data[2] != 0x90) return null;");
														w.Statement("if (data[3] != 0x00) return null;");

														w.Statement("var P1 = data[0];");
														w.Statement("var P2 = data[1];");
														w.Statement("var Pi8 = (short)(((P1 & 0xff) << 8) + (P2 & 0xff));");

														w.Statement("if (Pi8 < 0) return null;");


														w.Statement("return new " + Token.Name + " { Host = host, Token = Pi8 };");
													}
												);

											}
										);
									}

									#endregion

									//w.Statement("[Script]");
									w.Block("public interface ITransmitter",
										delegate
										{
											w.Statement("byte[] Transmit(params byte[] e);");
										}
									);

									w.Statement("public ITransmitter Transmitter;");



									//w.Statement("public const long ApplicationAID = " + TargetAssembly.GetCustomAttributes(typeof(AIDAttribute), false).Cast<AIDAttribute>().First().Value + "L;");
									//w.Statement("public const long DefaultInstallationSuffix = " + TargetType.GetCustomAttributes(typeof(AIDAttribute), false).Cast<AIDAttribute>().First().Value + "L;");

									Action<object[]> Transmit =
										c =>
										{
											w.Statement("return this.Transmitter.Transmit(" + c.Aggregate("",
												(seed, value) =>
												{
													var x = value is byte ? "0x" + ((byte)value).ToString("x2") :
														value is int ? "0x" + (((int)value) & 0xFF).ToString("x2") :
														value.ToString();

													if (string.IsNullOrEmpty(seed))
														return x;

													return seed + ", " + x;
												}
											) + ");");
										};

									w.Block("public byte[] SelectApplet()",
										delegate
										{
											var c = new AIDAttribute.Info(TargetType).ToSelectApplet().Select(k => (object)k).ToArray();

											Transmit(c);
										}
									);

									var EnumTypesToDefine = from x in source.SelectMany(k => k)
															from y in x.k.GetParameters()
															let yt = y.ParameterType
															where yt.IsEnum && Enum.GetUnderlyingType(yt) == typeof(byte)
															select yt;

									foreach (var EnumType in EnumTypesToDefine.Distinct())
									{
										w.Block("public enum " + EnumType.Name + " : byte",
											delegate
											{
												var Names = Enum.GetNames(EnumType);
												var Values = (byte[])Enum.GetValues(EnumType);

												for (int i = 0; i < Names.Length; i++)
												{
													w.Statement(Names[i] + " = " + Values[i] + ",");
												}
											}
										);
									}

									var ProxyInstructions = source.SelectMany(k => 
											
										k.Select((q, i) => new { q.k, q.CLA, INS = q.CLA.AutoAssignInstructions ? (q.INS.ToINS((byte)i)) : q.INS })
										
									).ToArray();

									foreach (var i in ProxyInstructions)
									{
										var ik = i.k;
										var CLA = i.CLA.CLA;

										ProxyInvoke(w, Transmit, ik, CLA, i.INS);
									}
								}
							);
						}
					);
					#endregion


				}
				#endregion

			}

		}
Esempio n. 2
0
		static void Main(string[] args)
		{


			var TargetAssembly = Assembly.LoadFile(Path.GetFullPath(args[0]));
			var TargetType = TargetAssembly.GetType(args[1], true);
			var TargetFile = args[2];
			var ProxyFullname = args[3];
			var ProxyNamespace = ProxyFullname.Substring(0, ProxyFullname.LastIndexOf("."));
			var ProxyName = ProxyFullname.Substring(ProxyFullname.LastIndexOf(".") + 1);

			AppDomain.CurrentDomain.AssemblyResolve += delegate(object sender, ResolveEventArgs args_)
			{

				string name = new AssemblyName(args_.Name).Name;


				string file_dll = new FileInfo(TargetAssembly.Location).Directory.FullName + @"\" + name + ".dll";
				string file_exe = new FileInfo(TargetAssembly.Location).Directory.FullName + @"\" + name + ".exe";


				var x = File.Exists(file_dll) ? Assembly.LoadFile(file_dll) :
								(File.Exists(file_exe) ? Assembly.LoadFile(file_exe) : null);

				return x;
			};

			var ExportedMethods =
							from SomeType in TargetType.GetCustomAttributes(typeof(AlchemyAttribute), false).Cast<AlchemyAttribute>()
							from m in SomeType.TargetType.GetMethods(BindingFlags.Static | BindingFlags.Public)
							let Parameters = m.GetParameters()
							select new { m, Parameters };

			var CModuleNamespacePartial = Path.GetFileNameWithoutExtension(TargetAssembly.Location);

			if (CModuleNamespacePartial.IndexOf(".") > -1)
				CModuleNamespacePartial = CModuleNamespacePartial.Substring(0, CModuleNamespacePartial.IndexOf("."));

			var CModuleNamespace = "cmodule." + CModuleNamespacePartial;

			using (var p = new ProtectiveFileStream(new FileInfo(TargetFile)))
			using (var s = new StreamWriter(p))
			using (var w = new CodeWriter(s))
			{
				p.NotModified +=
					delegate
					{
						Console.WriteLine("Not modified. " + TargetFile);
					};

				s.BaseStream.SetLength(0);

				w.Statement("// Generated by ScriptCoreLib.Alchemy.ExportGenerator");
				w.Statement("// Clear this file to force code generation.");

				#region cmodule
				w.Namespace(CModuleNamespace,
					delegate
					{
						w.Using("ScriptCoreLib");
						w.Using("ScriptCoreLib.ActionScript.flash.utils");
						w.Using("ScriptCoreLib.ActionScript.flash.display");

						w.Statement("[global::System.Runtime.CompilerServices.CompilerGenerated]");
						w.Statement("[Script(IsNative = true)]");
						w.Block("public class CLibInit",
							delegate
							{
								w.Block("public void supplyFile(string path, ByteArray data)", null);
								w.Block("public void putEnv(string key, string value)", null);
								w.Block("public void setSprite(Sprite sprite)", null);
								w.Block("public object init()",
									delegate
									{
										w.Statement("return default(object);");
									}
								);
							}
						);

					}
				);
				#endregion

				#region exported methods and main
				w.Namespace(TargetType.Namespace,
					delegate
					{
						w.Using("ScriptCoreLib");
						w.Using("ScriptCoreLib.Alchemy.Headers");
						w.Block("partial class " + TargetType.Name,
							delegate
							{


								#region exposed methods
								foreach (var k in ExportedMethods)
								{

									w.Statement("[global::System.Runtime.CompilerServices.CompilerGenerated]");
									w.Block("static AS3_h._AS3_Val " + k.m.Name + "(object self, AS3_h._AS3_Val args)",
										delegate
										{
											foreach (var Parameter in k.Parameters)
											{
												if (typeof(int) == Parameter.ParameterType)
													w.Statement("int " + Parameter.Name + ";");
												else
													throw new NotSupportedException();
											}

											if (k.Parameters.Length > 0)
												w.Statement("AS3_h.AS3_ArrayValue(args, \"" +
													string.Join(", ",
														k.Parameters.Select(
															Parameter =>
															{
																return "IntType";
															}
														).ToArray()
													)
													+ "\", __arglist(" +
													string.Join(", ",
														k.Parameters.Select(
															Parameter =>
															{
																return "out " + Parameter.Name;
															}
														).ToArray()
													)
													+ "));");

											w.Statement("var __value = " + k.m.DeclaringType.FullName + "." + k.m.Name + "(" +
												string.Join(", ",
													k.Parameters.Select(
														Parameter =>
														{
															return Parameter.Name;
														}
													).ToArray()
												)
												+ ");"
											);

											foreach (var Parameter in k.Parameters)
											{
												if (typeof(int) == Parameter.ParameterType)
													w.Statement(Parameter.Name + " = default(int);");
												else
													throw new NotSupportedException();
											}

											if (k.m.ReflectedType.IsClass)
											{
												w.Statement("return AS3_h.AS3_Ptr(__value);");
											}
											else if (k.m.ReflectedType == typeof(string))
											{
												w.Statement("return AS3_h.AS3_String(__value);");

											}
											else
											{
												throw new NotSupportedException();
											}
										}
									);
								}
								#endregion

								w.Statement("[global::System.Runtime.CompilerServices.CompilerGenerated]");
								w.Statement("[Script(NoDecoration = true)]");
								w.Block("static int main()",
									delegate
									{
										foreach (var k in ExportedMethods)
										{
											w.Statement("var __" + k.m.Name + " = AS3_h.AS3_Function(null, " + k.m.Name + ");");
										}

										w.Statement("var __result = AS3_h.AS3_Object(\"" +
											string.Join(",",
												ExportedMethods.Select(
													m =>
													{
														return m.m.Name + ": AS3ValType";
													}
												).ToArray()
											)
											+ "\", __arglist(" +
											string.Join(",",
												ExportedMethods.Select(
													m =>
													{
														return "__" + m.m.Name;
													}
												).ToArray()
											)
											+ "));");


										foreach (var k in ExportedMethods)
										{
											w.Statement("AS3_h.AS3_Release(__" + k.m.Name + ");");
										}

										w.Statement("AS3_h.AS3_LibInit(__result);");
										w.Statement("return 0;");

									}
								);
							}
						);
					}
				);
				#endregion

				w.Namespace(ProxyNamespace,
					delegate
					{
						w.Using("System");
						w.Using("ScriptCoreLib");
						w.Using("ScriptCoreLib.ActionScript");
						w.Using("ScriptCoreLib.ActionScript.Extensions");
						w.Using("ScriptCoreLib.ActionScript.flash.utils");

						w.Statement("[global::System.Runtime.CompilerServices.CompilerGenerated]");
						w.Statement("[Script]");
						w.Block("public static class " + ProxyName,
							delegate
							{
								w.Statement("public static ByteArray Memory;");

								w.Statement("[Script(OptimizedCode = @\"return (ns::gstate).ds\")]");
								w.Block("public static ByteArray get_ds(Namespace ns)",
									delegate
									{
										w.Statement("return default(ByteArray);");
									}
								);

								Func<MethodInfo, string> GetGenericTypes =
									m =>
									{
										var ReturnType = "";

										// a pointer
										if (m.ReturnType.IsArray)
											ReturnType = "uint";
										else if (m.ReturnType == typeof(string))
											ReturnType = "string";
										else if (m.ReturnType == typeof(int))
											ReturnType = "int";
										else throw new NotSupportedException(m.ReturnType.FullName);

										return string.Join(", ",
											m.GetParameters().Select(
												Parameter =>
												{
													if (Parameter.ParameterType == typeof(int))
														return "int";

													if (Parameter.ParameterType == typeof(string))
														return "string";

													throw new NotSupportedException();
												}
											).ToArray()
										)
										+ (m.GetParameters().Any() ? ", " : "")
										+ ReturnType;
									};


								foreach (var k in ExportedMethods)
								{
									w.Statement("public static readonly Func<" + GetGenericTypes(k.m) + "> " + k.m.Name + ";");
								}

								w.Block("static " + ProxyName + "()",
									delegate
									{
										w.Statement("var __loader = new " + CModuleNamespace + ".CLibInit();");
										w.Statement("var __lib = new DynamicDelegatesContainer { Subject = __loader.init() };");
										w.Statement(ProxyName + ".Memory = get_ds(new Namespace(\"" + CModuleNamespace + "\"));");

										foreach (var k in ExportedMethods)
										{
											w.Statement(ProxyName + "." + k.m.Name + " = __lib.ToFunc<" + GetGenericTypes(k.m) + ">(\"" + k.m.Name + "\");");
										}
									}
								);
							}
						);
					}
				);
			}
		}