diff --git a/Mono.Assembler/ILReader.cs b/Mono.Assembler/ILReader.cs new file mode 100755 index 0000000..88fa8de --- /dev/null +++ b/Mono.Assembler/ILReader.cs @@ -0,0 +1,164 @@ +// ILReader.cs +// Author: Sergey Chaban (serge@wildwestsoftware.com) + +using System; +using System.IO; +using System.Text; +using System.Collections; + +namespace Mono.Assembler +{ + /// + /// + public class ILReader + { + private StreamReader reader; + private Stack putback_stack; + private Location location; + private Location markedLocation; + + public ILReader(StreamReader reader) + { + this.reader = reader; + putback_stack = new Stack(); + + location = new Location(); + markedLocation = Location.Unknown; + } + + + /// + /// + public Location Location + { + get { return location; } + } + + + /// + /// Provides access to underlying StreamReader. + /// + public StreamReader BaseReader + { + get { return reader; } + } + + private int DoRead() + { + if (putback_stack.Count > 0) + return (char) putback_stack.Pop(); + + return reader.Read(); + } + + private int DoPeek() + { + if (putback_stack.Count > 0) + return (char) putback_stack.Peek(); + + return reader.Peek(); + } + + /// + /// + /// + public int Read() + { + int read = DoRead(); + if (read == '\n') + location.NewLine(); + else + location.NextColumn(); + return read; + } + + /// + /// + /// + public int Peek() + { + return DoPeek(); + } + + + /// + /// + public void Unread(char c) + { + putback_stack.Push(c); + + if ('\n' == c) + location.PreviousLine(); + + location.PreviousColumn(); + } + + + /// + /// + /// + public void Unread(char[] chars) + { + for (int i = chars.Length - 1; i >= 0; i--) + Unread(chars[i]); + } + + /// + /// + /// + public void Unread(int c) + { + Unread((char) c); + } + + + /// + /// + public void SkipWhitespace() + { + int ch = Read(); + for (; ch != -1 && Char.IsWhiteSpace((char) ch); ch = Read()) ; + if (ch != -1) Unread(ch); + } + + + /// + /// + /// + public string ReadToWhitespace() + { + StringBuilder sb = new StringBuilder(); + int ch = Read(); + for (; ch != -1 && !Char.IsWhiteSpace((char) ch); sb.Append((char) ch), ch = Read()) ; + if (ch != -1) Unread(ch); + return sb.ToString(); + } + + + /// + /// + public void MarkLocation() + { + if (markedLocation == Location.Unknown) + { + markedLocation = new Location(location); + } + else + { + markedLocation.CopyFrom(location); + } + } + + + /// + /// + public void RestoreLocation() + { + if (markedLocation != Location.Unknown) + { + location.CopyFrom(markedLocation); + } + } + } +} + diff --git a/Mono.Assembler/ILTables.cs b/Mono.Assembler/ILTables.cs new file mode 100755 index 0000000..77c9414 --- /dev/null +++ b/Mono.Assembler/ILTables.cs @@ -0,0 +1,328 @@ +// ILTables.cs +// Mechanically generated - DO NOT EDIT! +// +// (C) Sergey Chaban (serge@wildwestsoftware.com) + +using System; +using System.Collections; +using System.Reflection.Emit; + +namespace Mono.Assembler +{ + public sealed class ILTables + { + private static Hashtable keywords = null; + private static Hashtable directives = null; + private static readonly object mutex; + + + private ILTables() + { + } + + static ILTables() + { + mutex = new object(); + } + + private static void AllocTable(ref Hashtable tbl, int size) + { + lock (mutex) + { + if (tbl == null) + tbl = new Hashtable(size); + } + } + + public static Hashtable Directives + { + get + { + if (directives != null) return directives; + + AllocTable(ref directives, 300); + + directives[".addon"] = new ILToken(Token.D_ADDON, ".addon"); + directives[".algorithm"] = new ILToken(Token.D_ALGORITHM, ".algorithm"); + directives[".assembly"] = new ILToken(Token.D_ASSEMBLY, ".assembly"); + directives[".backing"] = new ILToken(Token.D_BACKING, ".backing"); + directives[".blob"] = new ILToken(Token.D_BLOB, ".blob"); + directives[".capability"] = new ILToken(Token.D_CAPABILITY, ".capability"); + directives[".cctor"] = new ILToken(Token.D_CCTOR, ".cctor"); + directives[".class"] = new ILToken(Token.D_CLASS, ".class"); + directives[".comtype"] = new ILToken(Token.D_COMTYPE, ".comtype"); + directives[".config"] = new ILToken(Token.D_CONFIG, ".config"); + directives[".imagebase"] = new ILToken(Token.D_IMAGEBASE, ".imagebase"); + directives[".corflags"] = new ILToken(Token.D_CORFLAGS, ".corflags"); + directives[".ctor"] = new ILToken(Token.D_CTOR, ".ctor"); + directives[".custom"] = new ILToken(Token.D_CUSTOM, ".custom"); + directives[".data"] = new ILToken(Token.D_DATA, ".data"); + directives[".emitbyte"] = new ILToken(Token.D_EMITBYTE, ".emitbyte"); + directives[".entrypoint"] = new ILToken(Token.D_ENTRYPOINT, ".entrypoint"); + directives[".event"] = new ILToken(Token.D_EVENT, ".event"); + directives[".exeloc"] = new ILToken(Token.D_EXELOC, ".exeloc"); + directives[".export"] = new ILToken(Token.D_EXPORT, ".export"); + directives[".field"] = new ILToken(Token.D_FIELD, ".field"); + directives[".file"] = new ILToken(Token.D_FILE, ".file"); + directives[".fire"] = new ILToken(Token.D_FIRE, ".fire"); + directives[".get"] = new ILToken(Token.D_GET, ".get"); + directives[".hash"] = new ILToken(Token.D_HASH, ".hash"); + directives[".implicitcom"] = new ILToken(Token.D_IMPLICITCOM, ".implicitcom"); + directives[".language"] = new ILToken(Token.D_LANGUAGE, ".language"); + directives[".line"] = new ILToken(Token.D_LINE, ".line"); + directives["#line"] = new ILToken(Token.D_XLINE, "#line"); + directives[".locale"] = new ILToken(Token.D_LOCALE, ".locale"); + directives[".locals"] = new ILToken(Token.D_LOCALS, ".locals"); + directives[".manifestres"] = new ILToken(Token.D_MANIFESTRES, ".manifestres"); + directives[".maxstack"] = new ILToken(Token.D_MAXSTACK, ".maxstack"); + directives[".method"] = new ILToken(Token.D_METHOD, ".method"); + directives[".mime"] = new ILToken(Token.D_MIME, ".mime"); + directives[".module"] = new ILToken(Token.D_MODULE, ".module"); + directives[".mresource"] = new ILToken(Token.D_MRESOURCE, ".mresource"); + directives[".namespace"] = new ILToken(Token.D_NAMESPACE, ".namespace"); + directives[".originator"] = new ILToken(Token.D_ORIGINATOR, ".originator"); + directives[".os"] = new ILToken(Token.D_OS, ".os"); + directives[".other"] = new ILToken(Token.D_OTHER, ".other"); + directives[".override"] = new ILToken(Token.D_OVERRIDE, ".override"); + directives[".pack"] = new ILToken(Token.D_PACK, ".pack"); + directives[".param"] = new ILToken(Token.D_PARAM, ".param"); + directives[".permission"] = new ILToken(Token.D_PERMISSION, ".permission"); + directives[".permissionset"] = new ILToken(Token.D_PERMISSIONSET, ".permissionset"); + directives[".processor"] = new ILToken(Token.D_PROCESSOR, ".processor"); + directives[".property"] = new ILToken(Token.D_PROPERTY, ".property"); + directives[".publickey"] = new ILToken(Token.D_PUBLICKEY, ".publickey"); + directives[".publickeytoken"] = new ILToken(Token.D_PUBLICKEYTOKEN, ".publickeytoken"); + directives[".removeon"] = new ILToken(Token.D_REMOVEON, ".removeon"); + directives[".set"] = new ILToken(Token.D_SET, ".set"); + directives[".size"] = new ILToken(Token.D_SIZE, ".size"); + directives[".stackreserve"] = new ILToken(Token.D_STACKRESERVE, ".stackreserve"); + directives[".subsystem"] = new ILToken(Token.D_SUBSYSTEM, ".subsystem"); + directives[".title"] = new ILToken(Token.D_TITLE, ".title"); + directives[".try"] = new ILToken(Token.D_TRY, ".try"); + directives[".ver"] = new ILToken(Token.D_VER, ".ver"); + directives[".vtable"] = new ILToken(Token.D_VTABLE, ".vtable"); + directives[".vtentry"] = new ILToken(Token.D_VTENTRY, ".vtentry"); + directives[".vtfixup"] = new ILToken(Token.D_VTFIXUP, ".vtfixup"); + directives[".zeroinit"] = new ILToken(Token.D_ZEROINIT, ".zeroinit"); + + return directives; + } + } + + + public static Hashtable Keywords + { + get + { + if (keywords != null) return keywords; + + AllocTable(ref keywords, 300); + + keywords["at"] = new ILToken(Token.K_AT, "at"); + keywords["as"] = new ILToken(Token.K_AS, "as"); + keywords["implicitcom"] = new ILToken(Token.K_IMPLICITCOM, "implicitcom"); + keywords["implicitres"] = new ILToken(Token.K_IMPLICITRES, "implicitres"); + keywords["noappdomain"] = new ILToken(Token.K_NOAPPDOMAIN, "noappdomain"); + keywords["noprocess"] = new ILToken(Token.K_NOPROCESS, "noprocess"); + keywords["nomachine"] = new ILToken(Token.K_NOMACHINE, "nomachine"); + keywords["extern"] = new ILToken(Token.K_EXTERN, "extern"); + keywords["instance"] = new ILToken(Token.K_INSTANCE, "instance"); + keywords["explicit"] = new ILToken(Token.K_EXPLICIT, "explicit"); + keywords["default"] = new ILToken(Token.K_DEFAULT, "default"); + keywords["vararg"] = new ILToken(Token.K_VARARG, "vararg"); + keywords["unmanaged"] = new ILToken(Token.K_UNMANAGED, "unmanaged"); + keywords["cdecl"] = new ILToken(Token.K_CDECL, "cdecl"); + keywords["stdcall"] = new ILToken(Token.K_STDCALL, "stdcall"); + keywords["thiscall"] = new ILToken(Token.K_THISCALL, "thiscall"); + keywords["fastcall"] = new ILToken(Token.K_FASTCALL, "fastcall"); + keywords["marshal"] = new ILToken(Token.K_MARSHAL, "marshal"); + keywords["in"] = new ILToken(Token.K_IN, "in"); + keywords["out"] = new ILToken(Token.K_OUT, "out"); + keywords["opt"] = new ILToken(Token.K_OPT, "opt"); + // Not a keyword according to ilasm 1.1 + // keywords ["lcid"] = new ILToken (Token.K_LCID, "lcid"); + //keywords ["retval"] = new ILToken (Token.K_RETVAL, "retval"); + keywords["static"] = new ILToken(Token.K_STATIC, "static"); + keywords["public"] = new ILToken(Token.K_PUBLIC, "public"); + keywords["private"] = new ILToken(Token.K_PRIVATE, "private"); + keywords["family"] = new ILToken(Token.K_FAMILY, "family"); + keywords["initonly"] = new ILToken(Token.K_INITONLY, "initonly"); + keywords["rtspecialname"] = new ILToken(Token.K_RTSPECIALNAME, "rtspecialname"); + keywords["specialname"] = new ILToken(Token.K_SPECIALNAME, "specialname"); + keywords["assembly"] = new ILToken(Token.K_ASSEMBLY, "assembly"); + keywords["famandassem"] = new ILToken(Token.K_FAMANDASSEM, "famandassem"); + keywords["famorassem"] = new ILToken(Token.K_FAMORASSEM, "famorassem"); + keywords["privatescope"] = new ILToken(Token.K_PRIVATESCOPE, "privatescope"); + keywords["literal"] = new ILToken(Token.K_LITERAL, "literal"); + keywords["notserialized"] = new ILToken(Token.K_NOTSERIALIZED, "notserialized"); + keywords["value"] = new ILToken(Token.K_VALUE, "value"); + keywords["not_in_gc_heap"] = new ILToken(Token.K_NOT_IN_GC_HEAP, "not_in_gc_heap"); + keywords["interface"] = new ILToken(Token.K_INTERFACE, "interface"); + keywords["sealed"] = new ILToken(Token.K_SEALED, "sealed"); + keywords["abstract"] = new ILToken(Token.K_ABSTRACT, "abstract"); + keywords["auto"] = new ILToken(Token.K_AUTO, "auto"); + keywords["sequential"] = new ILToken(Token.K_SEQUENTIAL, "sequential"); + keywords["ansi"] = new ILToken(Token.K_ANSI, "ansi"); + keywords["unicode"] = new ILToken(Token.K_UNICODE, "unicode"); + keywords["autochar"] = new ILToken(Token.K_AUTOCHAR, "autochar"); + keywords["bestfit"] = new ILToken(Token.K_BESTFIT, "bestfit"); + keywords["charmaperror"] = new ILToken(Token.K_CHARMAPERROR, "charmaperror"); + keywords["import"] = new ILToken(Token.K_IMPORT, "import"); + keywords["serializable"] = new ILToken(Token.K_SERIALIZABLE, "serializable"); + keywords["nested"] = new ILToken(Token.K_NESTED, "nested"); + keywords["lateinit"] = new ILToken(Token.K_LATEINIT, "lateinit"); + keywords["extends"] = new ILToken(Token.K_EXTENDS, "extends"); + keywords["implements"] = new ILToken(Token.K_IMPLEMENTS, "implements"); + keywords["final"] = new ILToken(Token.K_FINAL, "final"); + keywords["virtual"] = new ILToken(Token.K_VIRTUAL, "virtual"); + keywords["hidebysig"] = new ILToken(Token.K_HIDEBYSIG, "hidebysig"); + keywords["newslot"] = new ILToken(Token.K_NEWSLOT, "newslot"); + keywords["unmanagedexp"] = new ILToken(Token.K_UNMANAGEDEXP, "unmanagedexp"); + keywords["pinvokeimpl"] = new ILToken(Token.K_PINVOKEIMPL, "pinvokeimpl"); + keywords["nomangle"] = new ILToken(Token.K_NOMANGLE, "nomangle"); + keywords["ole"] = new ILToken(Token.K_OLE, "ole"); + keywords["lasterr"] = new ILToken(Token.K_LASTERR, "lasterr"); + keywords["winapi"] = new ILToken(Token.K_WINAPI, "winapi"); + keywords["native"] = new ILToken(Token.K_NATIVE, "native"); + keywords["il"] = new ILToken(Token.K_IL, "il"); + keywords["cil"] = new ILToken(Token.K_CIL, "cil"); + keywords["optil"] = new ILToken(Token.K_OPTIL, "optil"); + keywords["managed"] = new ILToken(Token.K_MANAGED, "managed"); + keywords["forwardref"] = new ILToken(Token.K_FORWARDREF, "forwardref"); + keywords["runtime"] = new ILToken(Token.K_RUNTIME, "runtime"); + keywords["internalcall"] = new ILToken(Token.K_INTERNALCALL, "internalcall"); + keywords["synchronized"] = new ILToken(Token.K_SYNCHRONIZED, "synchronized"); + keywords["noinlining"] = new ILToken(Token.K_NOINLINING, "noinlining"); + keywords["custom"] = new ILToken(Token.K_CUSTOM, "custom"); + keywords["fixed"] = new ILToken(Token.K_FIXED, "fixed"); + keywords["sysstring"] = new ILToken(Token.K_SYSSTRING, "sysstring"); + keywords["array"] = new ILToken(Token.K_ARRAY, "array"); + keywords["variant"] = new ILToken(Token.K_VARIANT, "variant"); + keywords["currency"] = new ILToken(Token.K_CURRENCY, "currency"); + keywords["syschar"] = new ILToken(Token.K_SYSCHAR, "syschar"); + keywords["void"] = new ILToken(Token.K_VOID, "void"); + keywords["bool"] = new ILToken(Token.K_BOOL, "bool"); + keywords["int8"] = new ILToken(Token.K_INT8, "int8"); + keywords["int16"] = new ILToken(Token.K_INT16, "int16"); + keywords["int32"] = new ILToken(Token.K_INT32, "int32"); + keywords["int64"] = new ILToken(Token.K_INT64, "int64"); + keywords["float32"] = new ILToken(Token.K_FLOAT32, "float32"); + keywords["float64"] = new ILToken(Token.K_FLOAT64, "float64"); + keywords["error"] = new ILToken(Token.K_ERROR, "error"); + keywords["unsigned"] = new ILToken(Token.K_UNSIGNED, "unsigned"); + keywords["uint"] = new ILToken(Token.K_UINT, "uint"); + keywords["uint8"] = new ILToken(Token.K_UINT8, "uint8"); + keywords["uint16"] = new ILToken(Token.K_UINT16, "uint16"); + keywords["uint32"] = new ILToken(Token.K_UINT32, "uint32"); + keywords["uint64"] = new ILToken(Token.K_UINT64, "uint64"); + keywords["decimal"] = new ILToken(Token.K_DECIMAL, "decimal"); + keywords["date"] = new ILToken(Token.K_DATE, "date"); + keywords["bstr"] = new ILToken(Token.K_BSTR, "bstr"); + keywords["lpstr"] = new ILToken(Token.K_LPSTR, "lpstr"); + keywords["lpwstr"] = new ILToken(Token.K_LPWSTR, "lpwstr"); + keywords["lptstr"] = new ILToken(Token.K_LPTSTR, "lptstr"); + keywords["objectref"] = new ILToken(Token.K_OBJECTREF, "objectref"); + keywords["iunknown"] = new ILToken(Token.K_IUNKNOWN, "iunknown"); + keywords["idispatch"] = new ILToken(Token.K_IDISPATCH, "idispatch"); + keywords["struct"] = new ILToken(Token.K_STRUCT, "struct"); + keywords["safearray"] = new ILToken(Token.K_SAFEARRAY, "safearray"); + keywords["int"] = new ILToken(Token.K_INT, "int"); + keywords["byvalstr"] = new ILToken(Token.K_BYVALSTR, "byvalstr"); + keywords["tbstr"] = new ILToken(Token.K_TBSTR, "tbstr"); + keywords["lpvoid"] = new ILToken(Token.K_LPVOID, "lpvoid"); + keywords["any"] = new ILToken(Token.K_ANY, "any"); + keywords["float"] = new ILToken(Token.K_FLOAT, "float"); + keywords["lpstruct"] = new ILToken(Token.K_LPSTRUCT, "lpstruct"); + keywords["null"] = new ILToken(Token.K_NULL, "null"); + // keywords ["ptr"] = new ILToken (Token.K_PTR, "ptr"); + keywords["vector"] = new ILToken(Token.K_VECTOR, "vector"); + keywords["hresult"] = new ILToken(Token.K_HRESULT, "hresult"); + keywords["carray"] = new ILToken(Token.K_CARRAY, "carray"); + keywords["userdefined"] = new ILToken(Token.K_USERDEFINED, "userdefined"); + keywords["record"] = new ILToken(Token.K_RECORD, "record"); + keywords["filetime"] = new ILToken(Token.K_FILETIME, "filetime"); + keywords["blob"] = new ILToken(Token.K_BLOB, "blob"); + keywords["stream"] = new ILToken(Token.K_STREAM, "stream"); + keywords["storage"] = new ILToken(Token.K_STORAGE, "storage"); + keywords["streamed_object"] = new ILToken(Token.K_STREAMED_OBJECT, "streamed_object"); + keywords["stored_object"] = new ILToken(Token.K_STORED_OBJECT, "stored_object"); + keywords["blob_object"] = new ILToken(Token.K_BLOB_OBJECT, "blob_object"); + keywords["cf"] = new ILToken(Token.K_CF, "cf"); + keywords["clsid"] = new ILToken(Token.K_CLSID, "clsid"); + keywords["method"] = new ILToken(Token.K_METHOD, "method"); + keywords["class"] = new ILToken(Token.K_CLASS, "class"); + keywords["pinned"] = new ILToken(Token.K_PINNED, "pinned"); + keywords["modreq"] = new ILToken(Token.K_MODREQ, "modreq"); + keywords["modopt"] = new ILToken(Token.K_MODOPT, "modopt"); + keywords["typedref"] = new ILToken(Token.K_TYPEDREF, "typedref"); + keywords["property"] = new ILToken(Token.K_PROPERTY, "property"); +#if NET_2_0 || BOOTSTRAP_NET_2_0 + keywords ["type"] = new ILToken (Token.K_TYPE, "type"); +#endif + keywords["refany"] = new ILToken(Token.K_TYPEDREF, "typedref"); + keywords["wchar"] = new ILToken(Token.K_WCHAR, "wchar"); + keywords["char"] = new ILToken(Token.K_CHAR, "char"); + keywords["fromunmanaged"] = new ILToken(Token.K_FROMUNMANAGED, "fromunmanaged"); + keywords["callmostderived"] = new ILToken(Token.K_CALLMOSTDERIVED, "callmostderived"); + keywords["bytearray"] = new ILToken(Token.K_BYTEARRAY, "bytearray"); + keywords["with"] = new ILToken(Token.K_WITH, "with"); + keywords["init"] = new ILToken(Token.K_INIT, "init"); + keywords["to"] = new ILToken(Token.K_TO, "to"); + keywords["catch"] = new ILToken(Token.K_CATCH, "catch"); + keywords["filter"] = new ILToken(Token.K_FILTER, "filter"); + keywords["finally"] = new ILToken(Token.K_FINALLY, "finally"); + keywords["fault"] = new ILToken(Token.K_FAULT, "fault"); + keywords["handler"] = new ILToken(Token.K_HANDLER, "handler"); + keywords["tls"] = new ILToken(Token.K_TLS, "tls"); + keywords["field"] = new ILToken(Token.K_FIELD, "field"); + keywords["request"] = new ILToken(Token.K_REQUEST, "request"); + keywords["demand"] = new ILToken(Token.K_DEMAND, "demand"); + keywords["assert"] = new ILToken(Token.K_ASSERT, "assert"); + keywords["deny"] = new ILToken(Token.K_DENY, "deny"); + keywords["permitonly"] = new ILToken(Token.K_PERMITONLY, "permitonly"); + keywords["linkcheck"] = new ILToken(Token.K_LINKCHECK, "linkcheck"); + keywords["inheritcheck"] = new ILToken(Token.K_INHERITCHECK, "inheritcheck"); + keywords["reqmin"] = new ILToken(Token.K_REQMIN, "reqmin"); + keywords["reqopt"] = new ILToken(Token.K_REQOPT, "reqopt"); + keywords["reqrefuse"] = new ILToken(Token.K_REQREFUSE, "reqrefuse"); + keywords["prejitgrant"] = new ILToken(Token.K_PREJITGRANT, "prejitgrant"); + keywords["prejitdeny"] = new ILToken(Token.K_PREJITDENY, "prejitdeny"); + keywords["noncasdemand"] = new ILToken(Token.K_NONCASDEMAND, "noncasdemand"); + keywords["noncaslinkdemand"] = new ILToken(Token.K_NONCASLINKDEMAND, "noncaslinkdemand"); + keywords["noncasinheritance"] = new ILToken(Token.K_NONCASINHERITANCE, "noncasinheritance"); + keywords["readonly"] = new ILToken(Token.K_READONLY, "readonly"); + keywords["nometadata"] = new ILToken(Token.K_NOMETADATA, "nometadata"); + keywords["algorithm"] = new ILToken(Token.K_ALGORITHM, "algorithm"); + keywords["fullorigin"] = new ILToken(Token.K_FULLORIGIN, "fullorigin"); + // keywords ["nan"] = new ILToken (Token.K_NAN, "nan"); + // keywords ["inf"] = new ILToken (Token.K_INF, "inf"); + // keywords ["publickey"] = new ILToken (Token.K_PUBLICKEY, "publickey"); + keywords["enablejittracking"] = new ILToken(Token.K_ENABLEJITTRACKING, "enablejittracking"); + keywords["disablejitoptimizer"] = new ILToken(Token.K_DISABLEJITOPTIMIZER, "disablejitoptimizer"); + keywords["retargetable"] = new ILToken(Token.K_RETARGETABLE, "retargetable"); + keywords["preservesig"] = new ILToken(Token.K_PRESERVESIG, "preservesig"); + keywords["beforefieldinit"] = new ILToken(Token.K_BEFOREFIELDINIT, "beforefieldinit"); + keywords["alignment"] = new ILToken(Token.K_ALIGNMENT, "alignment"); + keywords["nullref"] = new ILToken(Token.K_NULLREF, "nullref"); + keywords["valuetype"] = new ILToken(Token.K_VALUETYPE, "valuetype"); + keywords["compilercontrolled"] = new ILToken(Token.K_COMPILERCONTROLLED, "compilercontrolled"); + keywords["reqsecobj"] = new ILToken(Token.K_REQSECOBJ, "reqsecobj"); + keywords["enum"] = new ILToken(Token.K_ENUM, "enum"); + keywords["object"] = new ILToken(Token.K_OBJECT, "object"); + keywords["string"] = new ILToken(Token.K_STRING, "string"); + keywords["true"] = new ILToken(Token.K_TRUE, "true"); + keywords["false"] = new ILToken(Token.K_FALSE, "false"); + keywords["is"] = new ILToken(Token.K_IS, "is"); + keywords["on"] = new ILToken(Token.K_ON, "on"); + keywords["off"] = new ILToken(Token.K_OFF, "off"); + keywords["strict"] = new ILToken(Token.K_STRICT, "strict"); + + return keywords; + } + } + } + + // class ILTables +} + +// namespace Mono.ILASM \ No newline at end of file diff --git a/Mono.Assembler/ILToken.cs b/Mono.Assembler/ILToken.cs new file mode 100755 index 0000000..c702fc0 --- /dev/null +++ b/Mono.Assembler/ILToken.cs @@ -0,0 +1,244 @@ +// ILToken.cs +// Author: Sergey Chaban (serge@wildwestsoftware.com) + + +using System; + +namespace Mono.Assembler +{ + public class ILToken : ICloneable + { + internal int token; + internal object val; + + public static readonly ILToken Invalid; + public static readonly ILToken EOF; + + public static readonly ILToken Dot; + + public static readonly ILToken OpenBrace; + public static readonly ILToken CloseBrace; + public static readonly ILToken OpenBracket; + public static readonly ILToken CloseBracket; + public static readonly ILToken OpenParens; + public static readonly ILToken CloseParens; + public static readonly ILToken Comma; + public static readonly ILToken Colon; + public static readonly ILToken DoubleColon; + public static readonly ILToken Semicolon; + public static readonly ILToken Assign; + public static readonly ILToken Star; + public static readonly ILToken Ampersand; + public static readonly ILToken Plus; + public static readonly ILToken Slash; + public static readonly ILToken Bang; + public static readonly ILToken Ellipsis; + public static readonly ILToken Dash; + public static readonly ILToken OpenAngleBracket; + public static readonly ILToken CloseAngleBracket; + + private static readonly ILToken[] punctuations; + + /// + /// + static ILToken() + { + Invalid = new ILToken(-1, "invalid"); + EOF = new ILToken(Token.EOF, "eof"); + + Dot = new ILToken(Token.DOT, "."); + OpenBrace = new ILToken(Token.OPEN_BRACE, "{"); + CloseBrace = new ILToken(Token.CLOSE_BRACE, "}"); + OpenBracket = new ILToken(Token.OPEN_BRACKET, "["); + CloseBracket = new ILToken(Token.CLOSE_BRACKET, "]"); + OpenParens = new ILToken(Token.OPEN_PARENS, "("); + CloseParens = new ILToken(Token.CLOSE_PARENS, ")"); + Comma = new ILToken(Token.COMMA, ","); + Colon = new ILToken(Token.COLON, ":"); + DoubleColon = new ILToken(Token.DOUBLE_COLON, "::"); + Semicolon = new ILToken(Token.SEMICOLON, ";"); + Assign = new ILToken(Token.ASSIGN, "="); + Star = new ILToken(Token.STAR, "*"); + Ampersand = new ILToken(Token.AMPERSAND, "&"); + Plus = new ILToken(Token.PLUS, "+"); + Slash = new ILToken(Token.SLASH, "/"); + Bang = new ILToken(Token.BANG, "!"); + Ellipsis = new ILToken(Token.ELLIPSIS, "..."); + Dash = new ILToken(Token.DASH, "-"); + OpenAngleBracket = new ILToken(Token.OPEN_ANGLE_BRACKET, "<"); + CloseAngleBracket = new ILToken(Token.CLOSE_ANGLE_BRACKET, ">"); + + punctuations = new ILToken[] + { + OpenBrace, CloseBrace, + OpenBracket, CloseBracket, + OpenParens, CloseParens, + Comma, Colon, Semicolon, + Assign, Star, Ampersand, + Plus, Slash, Bang, + OpenAngleBracket, CloseAngleBracket + }; + } + + /// + /// + public ILToken() + { + } + + /// + /// + /// + /// + public ILToken(int token, object val) + { + this.token = token; + this.val = val; + } + + + /// + /// + /// + public ILToken(ILToken that) + { + this.token = that.token; + this.val = that.val; + } + + + /// + /// + public int TokenId + { + get { return token; } + } + + /// + /// + public object Value + { + get { return val; } + } + + + /// + /// + /// + public virtual void CopyFrom(ILToken that) + { + this.token = that.token; + this.val = that.val; + } + + + /// + /// + /// + public virtual object Clone() + { + return new ILToken(this); + } + + + /// + /// + /// + public override int GetHashCode() + { + int h = token; + if (val != null) h ^= val.GetHashCode(); + return h; + } + + + /// + /// + /// + public override string ToString() + { + return (token.ToString() + " : " + (val != null ? val.ToString() : "")); + } + + + /// + /// + /// + /// + public override bool Equals(object o) + { + bool res = (o != null); + + if (res) + { + res = Object.ReferenceEquals(this, o); + if (!res) + { + res = o is ILToken; + if (res) + { + ILToken that = o as ILToken; + res = (this.token == that.token) && (this.val.Equals(that.val)); + } + } + } + + return res; + } + + + private static bool EqImpl(ILToken t1, ILToken t2) + { + bool res = false; + if ((t1 as object) != null) + { + res = t1.Equals(t2); + } + else + { + res = ((t2 as object) == null); + } + + return res; + } + + + /// + /// + /// + /// + /// + public static bool operator ==(ILToken t1, ILToken t2) + { + return EqImpl(t1, t2); + } + + /// + /// + /// + /// + /// + public static bool operator !=(ILToken t1, ILToken t2) + { + return !EqImpl(t1, t2); + } + + + /// + /// + /// + /// + public static ILToken GetPunctuation(int ch) + { + int id = "{}[](),:;=*&+/!<>".IndexOf((char) ch); + ILToken res = null; + + if (id != -1) + { + res = punctuations[id]; + } + + return res; + } + } +} \ No newline at end of file diff --git a/Mono.Assembler/ILTokenizer.cs b/Mono.Assembler/ILTokenizer.cs new file mode 100755 index 0000000..9eb7695 --- /dev/null +++ b/Mono.Assembler/ILTokenizer.cs @@ -0,0 +1,417 @@ +// ILTokenizer.cs +// Author: Sergey Chaban (serge@wildwestsoftware.com) + +using System; +using System.IO; +using System.Text; +using System.Collections; +using System.Globalization; + +namespace Mono.Assembler +{ + public delegate void NewTokenEvent(object sender, NewTokenEventArgs args); + + public class NewTokenEventArgs : EventArgs + { + public readonly ILToken Token; + + public NewTokenEventArgs(ILToken token) + { + Token = token; + } + } + + public class ILTokenizer : ITokenStream + { + private static readonly string idchars = "_$@?.`"; + + private static Hashtable keywords; + private static Hashtable directives; + + private ILToken lastToken; + private ILReader reader; + private StringHelper strBuilder; + private NumberHelper numBuilder; + private bool in_byte_array; + + public event NewTokenEvent NewTokenEvent; + + static ILTokenizer() + { + keywords = ILTables.Keywords; + directives = ILTables.Directives; + } + + /// + /// + /// + public ILTokenizer(StreamReader reader) + { + this.reader = new ILReader(reader); + strBuilder = new StringHelper(this); + numBuilder = new NumberHelper(this); + lastToken = ILToken.Invalid.Clone() as ILToken; + } + + public ILReader Reader + { + get { return reader; } + } + + public Location Location + { + get { return reader.Location; } + } + + public bool InByteArray + { + get { return in_byte_array; } + set { in_byte_array = value; } + } + + public ILToken GetNextToken() + { + if (lastToken == ILToken.EOF) return ILToken.EOF; + + int ch; + int next; + ILToken res = ILToken.EOF.Clone() as ILToken; + + + while ((ch = reader.Read()) != -1) + { + // Comments + if (ch == '/') + { + next = reader.Peek(); + if (next == '/') + { + // double-slash comment, skip to the end of the line. + for (reader.Read(); + next != -1 && next != '\n'; + next = reader.Read()) ; + res.token = Token.SL_COMMENT; + break; + } + else if (next == '*') + { + reader.Read(); + for (next = reader.Read(); next != -1; next = reader.Read()) + { + if (next == '*' && reader.Peek() == '/') + { + reader.Read(); + goto end; + } + } + end: + res.token = Token.ML_COMMENT; + break; + } + } + + // HEXBYTES are flagged by the parser otherwise it is + // impossible to figure them out + if (in_byte_array) + { + string hx = String.Empty; + + if (Char.IsWhiteSpace((char) ch)) + continue; + + if (ch == ')') + { + res = ILToken.CloseParens; + break; + } + + if (!is_hex(ch)) + throw new ILTokenizingException(reader.Location, ((char) ch).ToString()); + hx += (char) ch; + if (is_hex(reader.Peek())) + hx += (char) reader.Read(); + else if (!Char.IsWhiteSpace((char) reader.Peek()) && reader.Peek() != ')') + throw new ILTokenizingException(reader.Location, + ((char) reader.Peek()).ToString()); + res.token = Token.HEXBYTE; + res.val = Byte.Parse(hx, NumberStyles.HexNumber); + + while (Char.IsWhiteSpace((char) reader.Peek())) + reader.Read(); + break; + } + + // Ellipsis + if (ch == '.' && reader.Peek() == '.') + { + reader.MarkLocation(); + int ch2 = reader.Read(); + if (reader.Peek() == '.') + { + res = ILToken.Ellipsis; + reader.Read(); + break; + } + reader.Unread(ch2); + reader.RestoreLocation(); + } + + if (ch == '.' || ch == '#') + { + next = reader.Peek(); + if (ch == '.' && Char.IsDigit((char) next)) + { + numBuilder.Start(ch); + reader.Unread(ch); + numBuilder.Build(); + if (numBuilder.ResultToken != ILToken.Invalid) + { + res.CopyFrom(numBuilder.ResultToken); + break; + } + } + else + { + if (strBuilder.Start(next) && strBuilder.TokenId == Token.ID) + { + reader.MarkLocation(); + string dirBody = strBuilder.Build(); + string dir = new string((char) ch, 1) + dirBody; + if (IsDirective(dir)) + { + res = ILTables.Directives[dir] as ILToken; + } + else + { + reader.Unread(dirBody.ToCharArray()); + reader.RestoreLocation(); + res = ILToken.Dot; + } + } + else + { + res = ILToken.Dot; + } + break; + } + } + + // Numbers && Hexbytes + if (numBuilder.Start(ch)) + { + if ((ch == '-') && !(Char.IsDigit((char) reader.Peek()))) + { + res = ILToken.Dash; + break; + } + else + { + reader.Unread(ch); + numBuilder.Build(); + if (numBuilder.ResultToken != ILToken.Invalid) + { + res.CopyFrom(numBuilder.ResultToken); + break; + } + } + } + + // Punctuation + ILToken punct = ILToken.GetPunctuation(ch); + if (punct != null) + { + if (punct == ILToken.Colon && reader.Peek() == ':') + { + reader.Read(); + res = ILToken.DoubleColon; + } + else + { + res = punct; + } + break; + } + + // ID | QSTRING | SQSTRING | INSTR_* | KEYWORD + if (strBuilder.Start(ch)) + { + reader.Unread(ch); + string val = strBuilder.Build(); + if (strBuilder.TokenId == Token.ID) + { + ILToken opcode; + next = reader.Peek(); + if (next == '.') + { + reader.MarkLocation(); + reader.Read(); + next = reader.Peek(); + if (IsIdChar((char) next)) + { + string opTail = BuildId(); + string full_str = String.Format("{0}.{1}", val, opTail); + opcode = InstrTable.GetToken(full_str); + + if (opcode == null) + { + if (strBuilder.TokenId != Token.ID) + { + reader.Unread(opTail.ToCharArray()); + reader.Unread('.'); + reader.RestoreLocation(); + res.val = val; + } + else + { + res.token = Token.COMP_NAME; + res.val = full_str; + } + break; + } + else + { + res = opcode; + break; + } + } + else if (Char.IsWhiteSpace((char) next)) + { + // Handle 'tail.' and 'unaligned.' + opcode = InstrTable.GetToken(val + "."); + if (opcode != null) + { + res = opcode; + break; + } + // Let the parser handle the dot + reader.Unread('.'); + } + } + opcode = InstrTable.GetToken(val); + if (opcode != null) + { + res = opcode; + break; + } + if (IsKeyword(val)) + { + res = ILTables.Keywords[val] as ILToken; + break; + } + } + + res.token = strBuilder.TokenId; + res.val = val; + break; + } + } + + OnNewToken(res); + lastToken.CopyFrom(res); + return res; + } + + + /// + /// + public ILToken NextToken + { + get { return GetNextToken(); } + } + + + /// + /// + public ILToken LastToken + { + get { return lastToken; } + } + + private bool is_hex(int e) + { + return (e >= '0' && e <= '9') || (e >= 'A' && e <= 'F') || (e >= 'a' && e <= 'f'); + } + + private static bool IsIdStartChar(char ch) + { + return (Char.IsLetter(ch) || (idchars.IndexOf(ch) != -1)); + } + + + private static bool IsIdChar(char ch) + { + return (Char.IsLetterOrDigit(ch) || (idchars.IndexOf(ch) != -1)); + } + + /// + /// + /// + /// + public static bool IsOpcode(string name) + { + return InstrTable.IsInstr(name); + } + + + /// + /// + /// + /// + public static bool IsDirective(string name) + { + char ch = name[0]; + bool res = (ch == '.' || ch == '#'); + + if (res) + { + res = directives.Contains(name); + } + + return res; + } + + private string BuildId() + { + StringBuilder idsb = new StringBuilder(); + int ch, last; + + last = -1; + while ((ch = reader.Read()) != -1) + { + if (IsIdChar((char) ch) || ch == '.') + { + idsb.Append((char) ch); + } + else + { + reader.Unread(ch); + // Never end an id on a DOT + if (last == '.') + { + reader.Unread(last); + idsb.Length -= 1; + } + break; + } + last = ch; + } + + return idsb.ToString(); + } + + /// + /// + /// + /// + public static bool IsKeyword(string name) + { + return keywords.Contains(name); + } + + private void OnNewToken(ILToken token) + { + if (NewTokenEvent != null) + NewTokenEvent(this, new NewTokenEventArgs(token)); + } + } +} \ No newline at end of file diff --git a/Mono.Assembler/ILTokenizingException.cs b/Mono.Assembler/ILTokenizingException.cs new file mode 100755 index 0000000..951627d --- /dev/null +++ b/Mono.Assembler/ILTokenizingException.cs @@ -0,0 +1,27 @@ +// +// Mono.ILASM.ILTokenizingException +// +// Author(s): +// Jackson Harper (jackson@ximian.com) +// +// Copyright 2004 Novell, Inc (http://www.novell.com) +// + + +using System; + +namespace Mono.Assembler +{ + public class ILTokenizingException : Exception + { + public readonly Location Location; + public readonly string Token; + + public ILTokenizingException(Location location, string token) + : base(token) + { + Location = location; + Token = token; + } + } +} diff --git a/Mono.Assembler/ITokenStream.cs b/Mono.Assembler/ITokenStream.cs new file mode 100755 index 0000000..c704ab2 --- /dev/null +++ b/Mono.Assembler/ITokenStream.cs @@ -0,0 +1,14 @@ +// ITokenStream.cs +// (C) Sergey Chaban (serge@wildwestsoftware.com) + +using System; +using System.Collections; + +namespace Mono.Assembler +{ + public interface ITokenStream + { + ILToken NextToken { get; } + ILToken LastToken { get; } + } +} \ No newline at end of file diff --git a/Mono.Assembler/InstrTable.cs b/Mono.Assembler/InstrTable.cs new file mode 100755 index 0000000..be5ba14 --- /dev/null +++ b/Mono.Assembler/InstrTable.cs @@ -0,0 +1,310 @@ +// +// Mono.ILASM.InstrTable +// +// Author(s): +// Jackson Harper (Jackson@LatitudeGeo.com) +// +// (C) 2003 Jackson Harper, All rights reserved +// + +using System.Collections; +using System.Reflection.Emit; + +namespace Mono.Assembler +{ + public class InstrTable + { + private static Hashtable inst_table; + + static InstrTable() + { + CreateInstTable(); + } + + public static ILToken GetToken(string str) + { + return inst_table[str] as ILToken; + } + + public static bool IsInstr(string str) + { + return inst_table.Contains(str); + } + + private static void CreateInstTable() + { + inst_table = new Hashtable(); + + inst_table["nop"] = new ILToken(Token.INSTR_NONE, OpCodes.Nop); + inst_table["break"] = new ILToken(Token.INSTR_NONE, OpCodes.Break); + inst_table["ldarg.0"] = new ILToken(Token.INSTR_NONE, OpCodes.Ldarg_0); + inst_table["ldarg.1"] = new ILToken(Token.INSTR_NONE, OpCodes.Ldarg_1); + inst_table["ldarg.2"] = new ILToken(Token.INSTR_NONE, OpCodes.Ldarg_2); + inst_table["ldarg.3"] = new ILToken(Token.INSTR_NONE, OpCodes.Ldarg_3); + inst_table["ldloc.0"] = new ILToken(Token.INSTR_NONE, OpCodes.Ldloc_0); + inst_table["ldloc.1"] = new ILToken(Token.INSTR_NONE, OpCodes.Ldloc_1); + inst_table["ldloc.2"] = new ILToken(Token.INSTR_NONE, OpCodes.Ldloc_2); + inst_table["ldloc.3"] = new ILToken(Token.INSTR_NONE, OpCodes.Ldloc_3); + inst_table["stloc.0"] = new ILToken(Token.INSTR_NONE, OpCodes.Stloc_0); + inst_table["stloc.1"] = new ILToken(Token.INSTR_NONE, OpCodes.Stloc_1); + inst_table["stloc.2"] = new ILToken(Token.INSTR_NONE, OpCodes.Stloc_2); + inst_table["stloc.3"] = new ILToken(Token.INSTR_NONE, OpCodes.Stloc_3); + inst_table["ldnull"] = new ILToken(Token.INSTR_NONE, OpCodes.Ldnull); + inst_table["ldc.i4.m1"] = new ILToken(Token.INSTR_NONE, OpCodes.Ldc_I4_M1); + inst_table["ldc.i4.M1"] = new ILToken(Token.INSTR_NONE, OpCodes.Ldc_I4_M1); + inst_table["ldc.i4.0"] = new ILToken(Token.INSTR_NONE, OpCodes.Ldc_I4_0); + inst_table["ldc.i4.1"] = new ILToken(Token.INSTR_NONE, OpCodes.Ldc_I4_1); + inst_table["ldc.i4.2"] = new ILToken(Token.INSTR_NONE, OpCodes.Ldc_I4_2); + inst_table["ldc.i4.3"] = new ILToken(Token.INSTR_NONE, OpCodes.Ldc_I4_3); + inst_table["ldc.i4.4"] = new ILToken(Token.INSTR_NONE, OpCodes.Ldc_I4_4); + inst_table["ldc.i4.5"] = new ILToken(Token.INSTR_NONE, OpCodes.Ldc_I4_5); + inst_table["ldc.i4.6"] = new ILToken(Token.INSTR_NONE, OpCodes.Ldc_I4_6); + inst_table["ldc.i4.7"] = new ILToken(Token.INSTR_NONE, OpCodes.Ldc_I4_7); + inst_table["ldc.i4.8"] = new ILToken(Token.INSTR_NONE, OpCodes.Ldc_I4_8); + inst_table["dup"] = new ILToken(Token.INSTR_NONE, OpCodes.Dup); + inst_table["pop"] = new ILToken(Token.INSTR_NONE, OpCodes.Pop); + inst_table["ret"] = new ILToken(Token.INSTR_NONE, OpCodes.Ret); + inst_table["ldind.i1"] = new ILToken(Token.INSTR_NONE, OpCodes.Ldind_I1); + inst_table["ldind.u1"] = new ILToken(Token.INSTR_NONE, OpCodes.Ldind_U1); + inst_table["ldind.i2"] = new ILToken(Token.INSTR_NONE, OpCodes.Ldind_I2); + inst_table["ldind.u2"] = new ILToken(Token.INSTR_NONE, OpCodes.Ldind_U2); + inst_table["ldind.i4"] = new ILToken(Token.INSTR_NONE, OpCodes.Ldind_I4); + inst_table["ldind.u4"] = new ILToken(Token.INSTR_NONE, OpCodes.Ldind_U4); + inst_table["ldind.i8"] = new ILToken(Token.INSTR_NONE, OpCodes.Ldind_I8); + inst_table["ldind.u8"] = new ILToken(Token.INSTR_NONE, OpCodes.Ldind_I8); + inst_table["ldind.i"] = new ILToken(Token.INSTR_NONE, OpCodes.Ldind_I); + inst_table["ldind.r4"] = new ILToken(Token.INSTR_NONE, OpCodes.Ldind_R4); + inst_table["ldind.r8"] = new ILToken(Token.INSTR_NONE, OpCodes.Ldind_R8); + inst_table["ldind.ref"] = new ILToken(Token.INSTR_NONE, OpCodes.Ldind_Ref); + inst_table["stind.ref"] = new ILToken(Token.INSTR_NONE, OpCodes.Stind_Ref); + inst_table["stind.i1"] = new ILToken(Token.INSTR_NONE, OpCodes.Stind_I1); + inst_table["stind.i2"] = new ILToken(Token.INSTR_NONE, OpCodes.Stind_I2); + inst_table["stind.i4"] = new ILToken(Token.INSTR_NONE, OpCodes.Stind_I4); + inst_table["stind.i8"] = new ILToken(Token.INSTR_NONE, OpCodes.Stind_I8); + inst_table["stind.r4"] = new ILToken(Token.INSTR_NONE, OpCodes.Stind_R4); + inst_table["stind.r8"] = new ILToken(Token.INSTR_NONE, OpCodes.Stind_R8); + inst_table["add"] = new ILToken(Token.INSTR_NONE, OpCodes.Add); + inst_table["sub"] = new ILToken(Token.INSTR_NONE, OpCodes.Sub); + inst_table["mul"] = new ILToken(Token.INSTR_NONE, OpCodes.Mul); + inst_table["div"] = new ILToken(Token.INSTR_NONE, OpCodes.Div); + inst_table["div.un"] = new ILToken(Token.INSTR_NONE, OpCodes.Div_Un); + inst_table["rem"] = new ILToken(Token.INSTR_NONE, OpCodes.Rem); + inst_table["rem.un"] = new ILToken(Token.INSTR_NONE, OpCodes.Rem_Un); + inst_table["and"] = new ILToken(Token.INSTR_NONE, OpCodes.And); + inst_table["or"] = new ILToken(Token.INSTR_NONE, OpCodes.Or); + inst_table["xor"] = new ILToken(Token.INSTR_NONE, OpCodes.Xor); + inst_table["shl"] = new ILToken(Token.INSTR_NONE, OpCodes.Shl); + inst_table["shr"] = new ILToken(Token.INSTR_NONE, OpCodes.Shr); + inst_table["shr.un"] = new ILToken(Token.INSTR_NONE, OpCodes.Shr_Un); + inst_table["neg"] = new ILToken(Token.INSTR_NONE, OpCodes.Neg); + inst_table["not"] = new ILToken(Token.INSTR_NONE, OpCodes.Not); + inst_table["conv.i1"] = new ILToken(Token.INSTR_NONE, OpCodes.Conv_I1); + inst_table["conv.i2"] = new ILToken(Token.INSTR_NONE, OpCodes.Conv_I2); + inst_table["conv.i4"] = new ILToken(Token.INSTR_NONE, OpCodes.Conv_I4); + inst_table["conv.i8"] = new ILToken(Token.INSTR_NONE, OpCodes.Conv_I8); + inst_table["conv.r4"] = new ILToken(Token.INSTR_NONE, OpCodes.Conv_R4); + inst_table["conv.r8"] = new ILToken(Token.INSTR_NONE, OpCodes.Conv_R8); + inst_table["conv.u4"] = new ILToken(Token.INSTR_NONE, OpCodes.Conv_U4); + inst_table["conv.u8"] = new ILToken(Token.INSTR_NONE, OpCodes.Conv_U8); + inst_table["conv.r.un"] = new ILToken(Token.INSTR_NONE, OpCodes.Conv_R_Un); + inst_table["throw"] = new ILToken(Token.INSTR_NONE, OpCodes.Throw); + inst_table["conv.ovf.i1.un"] = new ILToken(Token.INSTR_NONE, OpCodes.Conv_Ovf_I1_Un); + inst_table["conv.ovf.i2.un"] = new ILToken(Token.INSTR_NONE, OpCodes.Conv_Ovf_I2_Un); + inst_table["conv.ovf.i4.un"] = new ILToken(Token.INSTR_NONE, OpCodes.Conv_Ovf_I4_Un); + inst_table["conv.ovf.i8.un"] = new ILToken(Token.INSTR_NONE, OpCodes.Conv_Ovf_I8_Un); + inst_table["conf.ovf.u1.un"] = new ILToken(Token.INSTR_NONE, OpCodes.Conv_Ovf_U1_Un); + inst_table["conv.ovf.u2.un"] = new ILToken(Token.INSTR_NONE, OpCodes.Conv_Ovf_U2_Un); + inst_table["conv.ovf.u4.un"] = new ILToken(Token.INSTR_NONE, OpCodes.Conv_Ovf_U4_Un); + inst_table["conv.ovf.u8.un"] = new ILToken(Token.INSTR_NONE, OpCodes.Conv_Ovf_U8_Un); + inst_table["conv.ovf.i.un"] = new ILToken(Token.INSTR_NONE, OpCodes.Conv_Ovf_I_Un); + inst_table["conv.ovf.u.un"] = new ILToken(Token.INSTR_NONE, OpCodes.Conv_Ovf_U_Un); + inst_table["ldlen"] = new ILToken(Token.INSTR_NONE, OpCodes.Ldlen); + inst_table["ldelem.i1"] = new ILToken(Token.INSTR_NONE, OpCodes.Ldelem_I1); + inst_table["ldelem.u1"] = new ILToken(Token.INSTR_NONE, OpCodes.Ldelem_U1); + inst_table["ldelem.i2"] = new ILToken(Token.INSTR_NONE, OpCodes.Ldelem_I2); + inst_table["ldelem.u2"] = new ILToken(Token.INSTR_NONE, OpCodes.Ldelem_U2); + inst_table["ldelem.i4"] = new ILToken(Token.INSTR_NONE, OpCodes.Ldelem_I4); + inst_table["ldelem.u4"] = new ILToken(Token.INSTR_NONE, OpCodes.Ldelem_U4); + inst_table["ldelem.i8"] = new ILToken(Token.INSTR_NONE, OpCodes.Ldelem_I8); + inst_table["ldelem.u8"] = new ILToken(Token.INSTR_NONE, OpCodes.Ldelem_I8); + inst_table["ldelem.i"] = new ILToken(Token.INSTR_NONE, OpCodes.Ldelem_I); + inst_table["ldelem.r4"] = new ILToken(Token.INSTR_NONE, OpCodes.Ldelem_R4); + inst_table["ldelem.r8"] = new ILToken(Token.INSTR_NONE, OpCodes.Ldelem_R8); + inst_table["ldelem.ref"] = new ILToken(Token.INSTR_NONE, OpCodes.Ldelem_Ref); + inst_table["Stelem.i"] = new ILToken(Token.INSTR_NONE, OpCodes.Stelem_I); + inst_table["Stelem.i1"] = new ILToken(Token.INSTR_NONE, OpCodes.Stelem_I1); + inst_table["Stelem.i2"] = new ILToken(Token.INSTR_NONE, OpCodes.Stelem_I2); + inst_table["Stelem.i4"] = new ILToken(Token.INSTR_NONE, OpCodes.Stelem_I4); + inst_table["Stelem.i8"] = new ILToken(Token.INSTR_NONE, OpCodes.Stelem_I8); + inst_table["Stelem.r4"] = new ILToken(Token.INSTR_NONE, OpCodes.Stelem_R4); + inst_table["Stelem.r8"] = new ILToken(Token.INSTR_NONE, OpCodes.Stelem_R8); + inst_table["Stelem.ref"] = new ILToken(Token.INSTR_NONE, OpCodes.Stelem_Ref); + inst_table["conv.ovf.i1"] = new ILToken(Token.INSTR_NONE, OpCodes.Conv_Ovf_I1); + inst_table["conv.ovf.u1"] = new ILToken(Token.INSTR_NONE, OpCodes.Conv_Ovf_U1); + inst_table["conv.ovf.i2"] = new ILToken(Token.INSTR_NONE, OpCodes.Conv_Ovf_I2); + inst_table["conv.ovf.u2"] = new ILToken(Token.INSTR_NONE, OpCodes.Conv_Ovf_U2); + inst_table["conv.ovf.i4"] = new ILToken(Token.INSTR_NONE, OpCodes.Conv_Ovf_I4); + inst_table["conv.ovf.u4"] = new ILToken(Token.INSTR_NONE, OpCodes.Conv_Ovf_U4); + inst_table["conv.ovf.i8"] = new ILToken(Token.INSTR_NONE, OpCodes.Conv_Ovf_I8); + inst_table["conv.ovf.u8"] = new ILToken(Token.INSTR_NONE, OpCodes.Conv_Ovf_U8); + inst_table["conv.ovf.u1.un"] = new ILToken(Token.INSTR_NONE, OpCodes.Conv_Ovf_U1_Un); + inst_table["conv.ovf.u2.un"] = new ILToken(Token.INSTR_NONE, OpCodes.Conv_Ovf_U2_Un); + inst_table["conv.ovf.u4.un"] = new ILToken(Token.INSTR_NONE, OpCodes.Conv_Ovf_U4_Un); + inst_table["conv.ovf.u8.un"] = new ILToken(Token.INSTR_NONE, OpCodes.Conv_Ovf_U8_Un); + inst_table["conv.ovf.i1.un"] = new ILToken(Token.INSTR_NONE, OpCodes.Conv_Ovf_I1_Un); + inst_table["conv.ovf.i2.un"] = new ILToken(Token.INSTR_NONE, OpCodes.Conv_Ovf_I2_Un); + inst_table["conv.ovf.i4.un"] = new ILToken(Token.INSTR_NONE, OpCodes.Conv_Ovf_I4_Un); + inst_table["conv.ovf.i8.un"] = new ILToken(Token.INSTR_NONE, OpCodes.Conv_Ovf_I8_Un); + inst_table["ckfinite"] = new ILToken(Token.INSTR_NONE, OpCodes.Ckfinite); + inst_table["conv.u2"] = new ILToken(Token.INSTR_NONE, OpCodes.Conv_U2); + inst_table["conv.u1"] = new ILToken(Token.INSTR_NONE, OpCodes.Conv_U1); + inst_table["conv.i"] = new ILToken(Token.INSTR_NONE, OpCodes.Conv_I); + inst_table["conv.ovf.i"] = new ILToken(Token.INSTR_NONE, OpCodes.Conv_Ovf_I); + inst_table["conv.ovf.u"] = new ILToken(Token.INSTR_NONE, OpCodes.Conv_Ovf_U); + inst_table["add.ovf"] = new ILToken(Token.INSTR_NONE, OpCodes.Add_Ovf); + inst_table["add.ovf.un"] = new ILToken(Token.INSTR_NONE, OpCodes.Add_Ovf_Un); + inst_table["mul.ovf"] = new ILToken(Token.INSTR_NONE, OpCodes.Mul_Ovf); + inst_table["mul.ovf.un"] = new ILToken(Token.INSTR_NONE, OpCodes.Mul_Ovf_Un); + inst_table["sub.ovf"] = new ILToken(Token.INSTR_NONE, OpCodes.Sub_Ovf); + inst_table["sub.ovf.un"] = new ILToken(Token.INSTR_NONE, OpCodes.Sub_Ovf_Un); + inst_table["endfinally"] = new ILToken(Token.INSTR_NONE, OpCodes.Endfinally); + // endfault is really just an alias for endfinally + inst_table["endfault"] = new ILToken(Token.INSTR_NONE, OpCodes.Endfinally); + inst_table["stind.i"] = new ILToken(Token.INSTR_NONE, OpCodes.Stind_I); + inst_table["conv.u"] = new ILToken(Token.INSTR_NONE, OpCodes.Conv_U); + inst_table["arglist"] = new ILToken(Token.INSTR_NONE, OpCodes.Arglist); + inst_table["ceq"] = new ILToken(Token.INSTR_NONE, OpCodes.Ceq); + inst_table["cgt"] = new ILToken(Token.INSTR_NONE, OpCodes.Cgt); + inst_table["cgt.un"] = new ILToken(Token.INSTR_NONE, OpCodes.Cgt_Un); + inst_table["clt"] = new ILToken(Token.INSTR_NONE, OpCodes.Clt); + inst_table["clt.un"] = new ILToken(Token.INSTR_NONE, OpCodes.Clt_Un); + inst_table["localloc"] = new ILToken(Token.INSTR_NONE, OpCodes.Localloc); + inst_table["endfilter"] = new ILToken(Token.INSTR_NONE, OpCodes.Endfilter); + inst_table["volatile."] = new ILToken(Token.INSTR_NONE, OpCodes.Volatile); + inst_table["tail."] = new ILToken(Token.INSTR_NONE, OpCodes.Tailcall); + inst_table["cpblk"] = new ILToken(Token.INSTR_NONE, OpCodes.Cpblk); + inst_table["initblk"] = new ILToken(Token.INSTR_NONE, OpCodes.Initblk); + inst_table["rethrow"] = new ILToken(Token.INSTR_NONE, OpCodes.Rethrow); + inst_table["refanytype"] = new ILToken(Token.INSTR_NONE, OpCodes.Refanytype); + inst_table["readonly."] = new ILToken(Token.INSTR_NONE, OpCodes.Readonly); + + // + // Int operations + // + + // param + inst_table["ldarg"] = new ILToken(Token.INSTR_PARAM, OpCodes.Ldarg); + inst_table["ldarga"] = new ILToken(Token.INSTR_PARAM, OpCodes.Ldarga); + inst_table["starg"] = new ILToken(Token.INSTR_PARAM, OpCodes.Starg); + inst_table["ldarg.s"] = new ILToken(Token.INSTR_PARAM, OpCodes.Ldarg_S); + inst_table["ldarga.s"] = new ILToken(Token.INSTR_PARAM, OpCodes.Ldarga_S); + inst_table["starg.s"] = new ILToken(Token.INSTR_PARAM, OpCodes.Starg_S); + + // local + inst_table["ldloc"] = new ILToken(Token.INSTR_LOCAL, OpCodes.Ldloc); + inst_table["ldloca"] = new ILToken(Token.INSTR_LOCAL, OpCodes.Ldloca); + inst_table["stloc"] = new ILToken(Token.INSTR_LOCAL, OpCodes.Stloc); + inst_table["ldloc.s"] = new ILToken(Token.INSTR_LOCAL, OpCodes.Ldloc_S); + inst_table["ldloca.s"] = new ILToken(Token.INSTR_LOCAL, OpCodes.Ldloca_S); + inst_table["stloc.s"] = new ILToken(Token.INSTR_LOCAL, OpCodes.Stloc_S); + + inst_table["ldc.i4.s"] = new ILToken(Token.INSTR_I, OpCodes.Ldc_I4_S); + inst_table["ldc.i4"] = new ILToken(Token.INSTR_I, OpCodes.Ldc_I4); + inst_table["unaligned."] = new ILToken(Token.INSTR_I, OpCodes.Unaligned); + + // + // Type operations + // + + inst_table["cpobj"] = new ILToken(Token.INSTR_TYPE, OpCodes.Cpobj); + inst_table["ldobj"] = new ILToken(Token.INSTR_TYPE, OpCodes.Ldobj); + inst_table["castclass"] = new ILToken(Token.INSTR_TYPE, OpCodes.Castclass); + inst_table["isinst"] = new ILToken(Token.INSTR_TYPE, OpCodes.Isinst); + inst_table["unbox"] = new ILToken(Token.INSTR_TYPE, OpCodes.Unbox); + inst_table["unbox.any"] = new ILToken(Token.INSTR_TYPE, OpCodes.Unbox_Any); + inst_table["stobj"] = new ILToken(Token.INSTR_TYPE, OpCodes.Stobj); + inst_table["box"] = new ILToken(Token.INSTR_TYPE, OpCodes.Box); + inst_table["newarr"] = new ILToken(Token.INSTR_TYPE, OpCodes.Newarr); + inst_table["ldelema"] = new ILToken(Token.INSTR_TYPE, OpCodes.Ldelema); + inst_table["refanyval"] = new ILToken(Token.INSTR_TYPE, OpCodes.Refanyval); + inst_table["mkrefany"] = new ILToken(Token.INSTR_TYPE, OpCodes.Mkrefany); + inst_table["initobj"] = new ILToken(Token.INSTR_TYPE, OpCodes.Initobj); + inst_table["sizeof"] = new ILToken(Token.INSTR_TYPE, OpCodes.Sizeof); + inst_table["stelem"] = new ILToken(Token.INSTR_TYPE, OpCodes.Stelem); + inst_table["ldelem"] = new ILToken(Token.INSTR_TYPE, OpCodes.Ldelem); + inst_table["stelem.any"] = new ILToken(Token.INSTR_TYPE, OpCodes.Stelem); + inst_table["ldelem.any"] = new ILToken(Token.INSTR_TYPE, OpCodes.Ldelem); + inst_table["constrained."] = new ILToken(Token.INSTR_TYPE, OpCodes.Constrained); + + // + // MethodRef operations + // + + inst_table["jmp"] = new ILToken(Token.INSTR_METHOD, OpCodes.Jmp); + inst_table["call"] = new ILToken(Token.INSTR_METHOD, OpCodes.Call); + inst_table["callvirt"] = new ILToken(Token.INSTR_METHOD, OpCodes.Callvirt); + inst_table["newobj"] = new ILToken(Token.INSTR_METHOD, OpCodes.Newobj); + inst_table["ldftn"] = new ILToken(Token.INSTR_METHOD, OpCodes.Ldftn); + inst_table["ldvirtftn"] = new ILToken(Token.INSTR_METHOD, OpCodes.Ldvirtftn); + + // + // FieldRef instructions + // + + inst_table["ldfld"] = new ILToken(Token.INSTR_FIELD, OpCodes.Ldfld); + inst_table["ldflda"] = new ILToken(Token.INSTR_FIELD, OpCodes.Ldflda); + inst_table["stfld"] = new ILToken(Token.INSTR_FIELD, OpCodes.Stfld); + inst_table["ldsfld"] = new ILToken(Token.INSTR_FIELD, OpCodes.Ldsfld); + inst_table["ldsflda"] = new ILToken(Token.INSTR_FIELD, OpCodes.Ldsflda); + inst_table["stsfld"] = new ILToken(Token.INSTR_FIELD, OpCodes.Stsfld); + + // + // Branch Instructions + // + + inst_table["br"] = new ILToken(Token.INSTR_BRTARGET, OpCodes.Br); + inst_table["brfalse"] = new ILToken(Token.INSTR_BRTARGET, OpCodes.Brfalse); + inst_table["brzero"] = new ILToken(Token.INSTR_BRTARGET, OpCodes.Brfalse); + inst_table["brnull"] = new ILToken(Token.INSTR_BRTARGET, OpCodes.Brfalse); + inst_table["brtrue"] = new ILToken(Token.INSTR_BRTARGET, OpCodes.Brtrue); + inst_table["beq"] = new ILToken(Token.INSTR_BRTARGET, OpCodes.Beq); + inst_table["bge"] = new ILToken(Token.INSTR_BRTARGET, OpCodes.Bge); + inst_table["bgt"] = new ILToken(Token.INSTR_BRTARGET, OpCodes.Bgt); + inst_table["ble"] = new ILToken(Token.INSTR_BRTARGET, OpCodes.Ble); + inst_table["blt"] = new ILToken(Token.INSTR_BRTARGET, OpCodes.Blt); + inst_table["bne.un"] = new ILToken(Token.INSTR_BRTARGET, OpCodes.Bne_Un); + inst_table["bge.un"] = new ILToken(Token.INSTR_BRTARGET, OpCodes.Bge_Un); + inst_table["bgt.un"] = new ILToken(Token.INSTR_BRTARGET, OpCodes.Bgt_Un); + inst_table["ble.un"] = new ILToken(Token.INSTR_BRTARGET, OpCodes.Ble_Un); + inst_table["blt.un"] = new ILToken(Token.INSTR_BRTARGET, OpCodes.Blt_Un); + inst_table["leave"] = new ILToken(Token.INSTR_BRTARGET, OpCodes.Leave); + + inst_table["br.s"] = new ILToken(Token.INSTR_BRTARGET, OpCodes.Br_S); + inst_table["brfalse.s"] = new ILToken(Token.INSTR_BRTARGET, OpCodes.Brfalse_S); + inst_table["brtrue.s"] = new ILToken(Token.INSTR_BRTARGET, OpCodes.Brtrue_S); + inst_table["beq.s"] = new ILToken(Token.INSTR_BRTARGET, OpCodes.Beq_S); + inst_table["bge.s"] = new ILToken(Token.INSTR_BRTARGET, OpCodes.Bge_S); + inst_table["bgt.s"] = new ILToken(Token.INSTR_BRTARGET, OpCodes.Bgt_S); + inst_table["ble.s"] = new ILToken(Token.INSTR_BRTARGET, OpCodes.Ble_S); + inst_table["blt.s"] = new ILToken(Token.INSTR_BRTARGET, OpCodes.Blt_S); + inst_table["bne.un.s"] = new ILToken(Token.INSTR_BRTARGET, OpCodes.Bne_Un_S); + inst_table["bge.un.s"] = new ILToken(Token.INSTR_BRTARGET, OpCodes.Bge_Un_S); + inst_table["bgt.un.s"] = new ILToken(Token.INSTR_BRTARGET, OpCodes.Bgt_Un_S); + inst_table["ble.un.s"] = new ILToken(Token.INSTR_BRTARGET, OpCodes.Ble_Un_S); + inst_table["blt.un.s"] = new ILToken(Token.INSTR_BRTARGET, OpCodes.Blt_Un_S); + inst_table["leave.s"] = new ILToken(Token.INSTR_BRTARGET, OpCodes.Leave_S); + + // + // Misc other instructions + // + + inst_table["ldstr"] = new ILToken(Token.INSTR_STRING, OpCodes.Ldstr); + inst_table["ldc.r4"] = new ILToken(Token.INSTR_R, OpCodes.Ldc_R4); + inst_table["ldc.r8"] = new ILToken(Token.INSTR_R, OpCodes.Ldc_R8); + inst_table["ldc.i8"] = new ILToken(Token.INSTR_I8, OpCodes.Ldc_I8); + inst_table["switch"] = new ILToken(Token.INSTR_SWITCH, OpCodes.Switch); + inst_table["calli"] = new ILToken(Token.INSTR_SIG, OpCodes.Calli); + inst_table["ldtoken"] = new ILToken(Token.INSTR_TOK, OpCodes.Ldtoken); + } + } +} \ No newline at end of file diff --git a/Mono.Assembler/InstrToken.cs b/Mono.Assembler/InstrToken.cs new file mode 100755 index 0000000..7a46e5e --- /dev/null +++ b/Mono.Assembler/InstrToken.cs @@ -0,0 +1,101 @@ +// InstrToken.cs +// Author: Sergey Chaban (serge@wildwestsoftware.com) + +using System; +using System.Reflection.Emit; + +namespace Mono.Assembler +{ + public class InstrToken : ILToken + { + /// + /// + public InstrToken(OpCode opcode) + { + this.val = opcode; + token = GetInstrType(opcode); + } + + + /// + /// + /// + /// + public static int GetInstrType(OpCode opcode) + { + OperandType t = opcode.OperandType; + int token = Token.UNKNOWN; + + switch (t) + { + case OperandType.InlineBrTarget: + case OperandType.ShortInlineBrTarget: + token = Token.INSTR_BRTARGET; + break; + + case OperandType.InlineField: + token = Token.INSTR_FIELD; + break; + + case OperandType.InlineI: + case OperandType.ShortInlineI: + token = Token.INSTR_I; + break; + + case OperandType.InlineI8: + token = Token.INSTR_I8; + break; + + case OperandType.InlineMethod: + token = Token.INSTR_METHOD; + break; + + case OperandType.InlineNone: + token = Token.INSTR_NONE; + break; + + case OperandType.InlinePhi: + token = Token.INSTR_PHI; + break; + + case OperandType.InlineR: + case OperandType.ShortInlineR: + token = Token.INSTR_R; + break; + + /* + case OperandType.InlineRVA: + token = Token.INSTR_RVA; + break; + */ + + case OperandType.InlineSig: + token = Token.INSTR_SIG; + break; + + case OperandType.InlineString: + token = Token.INSTR_STRING; + break; + + case OperandType.InlineSwitch: + token = Token.INSTR_SWITCH; + break; + + case OperandType.InlineTok: + token = Token.INSTR_TOK; + break; + + case OperandType.InlineType: + token = Token.INSTR_TYPE; + break; + + case OperandType.InlineVar: + case OperandType.ShortInlineVar: + token = Token.INSTR_VAR; + break; + } + + return token; + } + } +} \ No newline at end of file diff --git a/Mono.Assembler/Location.cs b/Mono.Assembler/Location.cs new file mode 100755 index 0000000..2c2cc13 --- /dev/null +++ b/Mono.Assembler/Location.cs @@ -0,0 +1,103 @@ +// Location.cs +// Author: Sergey Chaban (serge@wildwestsoftware.com) + +using System; + +namespace Mono.Assembler +{ + /// + /// + public class Location : ICloneable + { + internal int line; + internal int column; + + + /// + /// + public static readonly Location Unknown = new Location(-1, -1); + + /// + /// + public Location() + { + line = 1; + column = 1; + } + + /// + /// + /// + /// + public Location(int line, int column) + { + this.line = line; + this.column = column; + } + + + /// + /// + /// + public Location(Location that) + { + this.line = that.line; + this.column = that.column; + } + + + /// + /// + public void NewLine() + { + ++line; + column = 1; + } + + + /// + /// + public void PreviousLine() + { + --line; + column = 1; + } + + /// + /// + public void NextColumn() + { + ++column; + } + + /// + /// + public void PreviousColumn() + { + --column; + } + + /// + /// + /// + public void CopyFrom(Location other) + { + this.line = other.line; + this.column = other.column; + } + + + /// + /// + /// + public virtual object Clone() + { + return new Location(this); + } + + public override string ToString() + { + return "line (" + line + ") column (" + column + ")"; + } + } +} \ No newline at end of file diff --git a/Mono.Assembler/NumberHelper.cs b/Mono.Assembler/NumberHelper.cs new file mode 100755 index 0000000..df8e628 --- /dev/null +++ b/Mono.Assembler/NumberHelper.cs @@ -0,0 +1,238 @@ +// NumberHelper.cs +// Author: Sergey Chaban (serge@wildwestsoftware.com) + +using System; +using System.Text; +using System.Globalization; + +namespace Mono.Assembler +{ + /// + /// + internal class NumberHelper : StringHelperBase + { + private ILToken result; + + /// + /// + /// + public NumberHelper(ILTokenizer host) : base(host) + { + Reset(); + } + + + private void Reset() + { + result = ILToken.Invalid.Clone() as ILToken; + } + + /// + /// + /// + public override bool Start(char ch) + { + bool res = (Char.IsDigit(ch) || ch == '-' || (ch == '.' && Char.IsDigit((char) host.Reader.Peek()))); + Reset(); + return res; + } + + private bool is_hex(int e) + { + return (e >= '0' && e <= '9') || (e >= 'A' && e <= 'F') || (e >= 'a' && e <= 'f'); + } + + private bool is_sign(int ch) + { + return ((ch == '+') || (ch == '-')); + } + + private bool is_e(int ch) + { + return ((ch == 'e') || (ch == 'E')); + } + + /// + /// + /// + public override string Build() + { + ILReader reader = host.Reader; + reader.MarkLocation(); + StringBuilder num_builder = new StringBuilder(); + string num; + int ch; + int peek; + bool is_real = false; + bool dec_found = false; + + NumberStyles nstyles = NumberStyles.AllowExponent | NumberStyles.AllowDecimalPoint | + NumberStyles.AllowLeadingSign; + + ch = reader.Read(); + peek = reader.Peek(); + reader.Unread(ch); + + if (ch == '0' && (peek == 'x' || peek == 'X')) + return BuildHex(); + + if (is_sign(reader.Peek())) + num_builder.Append((char) reader.Read()); + + do + { + ch = reader.Read(); + peek = reader.Peek(); + num_builder.Append((char) ch); + + if (is_e(ch)) + { + if (is_real) + throw new ILTokenizingException(reader.Location, num_builder.ToString()); + + is_real = true; + } + if (ch == '.') + dec_found = true; + if (!is_hex(peek) && + !(peek == '.' && !dec_found) && !is_e(peek) && + !(is_sign(peek) && is_real)) + { + break; + } + } while (ch != -1); + + num = num_builder.ToString(); + + // Check for hexbytes + if (num.Length == 2) + { + if (Char.IsLetter(num[0]) || Char.IsLetter(num[1])) + { + result.token = Token.HEXBYTE; + result.val = Byte.Parse(num, NumberStyles.HexNumber); + return num; + } + } + + if (ch == '.' && peek == '.') + { + num = num.Substring(0, num.Length - 1); + reader.Unread('.'); + dec_found = false; + } + else if (ch == '.') + { + num += '0'; + } + + if (!dec_found && !is_real) + { + try + { + long i = Int64.Parse(num, nstyles); + result.token = Token.INT64; + result.val = i; + + return num; + } + catch + { + } + + try + { + long i = (long) UInt64.Parse(num, nstyles); + result.token = Token.INT64; + result.val = i; + + return num; + } + catch + { + } + } + + try + { + double d = Double.Parse(num, nstyles, NumberFormatInfo.InvariantInfo); + result.token = Token.FLOAT64; + result.val = d; + } + catch + { + reader.Unread(num.ToCharArray()); + reader.RestoreLocation(); + num = String.Empty; + Reset(); + throw new ILTokenizingException(reader.Location, num_builder.ToString()); + } + return num; + } + + public string BuildHex() + { + ILReader reader = host.Reader; + reader.MarkLocation(); + StringBuilder num_builder = new StringBuilder(); + NumberStyles nstyles = NumberStyles.HexNumber; + + string num; + int ch; + int peek; + + ch = reader.Read(); + if (ch != '0') + throw new ILTokenizingException(reader.Location, ((char) ch).ToString()); + + ch = reader.Read(); + + if (ch != 'x' && ch != 'X') + throw new ILTokenizingException(reader.Location, "0" + (char) ch); + + do + { + ch = reader.Read(); + peek = reader.Peek(); + num_builder.Append((char) ch); + + if (!is_hex((char) peek)) + break; + + if (num_builder.Length == 32) + throw new ILTokenizingException(reader.Location, num_builder.ToString()); + } while (ch != -1); + + num = num_builder.ToString(); + + try + { + long i = (long) UInt64.Parse(num, nstyles); + //if (i < Int32.MinValue || i > Int32.MaxValue) { + result.token = Token.INT64; + result.val = i; + //} else { + // result.token = Token.INT32; + // result.val = (int) i; + //} + } + catch + { + string tnum = num; + reader.Unread(num.ToCharArray()); + reader.RestoreLocation(); + num = String.Empty; + Reset(); + throw new ILTokenizingException(reader.Location, tnum); + } + return num; + } + + /// + /// + public ILToken ResultToken + { + get { return result; } + } + } +} \ No newline at end of file diff --git a/Mono.Assembler/StringHelper.cs b/Mono.Assembler/StringHelper.cs new file mode 100755 index 0000000..5a6b3a7 --- /dev/null +++ b/Mono.Assembler/StringHelper.cs @@ -0,0 +1,161 @@ +// StringHelper.cs +// Author: Sergey Chaban (serge@wildwestsoftware.com) + +using System; +using System.Text; + +namespace Mono.Assembler +{ + /// + /// + internal class StringHelper : StringHelperBase + { + private static readonly string startIdChars = "#$@_"; + private static readonly string idChars = "_$@?`"; + + /// + /// + /// + public StringHelper(ILTokenizer host) : base(host) + { + } + + + /// + /// + /// + public override bool Start(char ch) + { + mode = Token.UNKNOWN; + + if (Char.IsLetter(ch) || startIdChars.IndexOf(ch) != -1) + { + mode = Token.ID; + } + else if (ch == '\'') + { + mode = Token.SQSTRING; + } + else if (ch == '"') + { + mode = Token.QSTRING; + } + + return (mode != Token.UNKNOWN); + } + + + private static bool IsIdChar(int c) + { + char ch = (char) c; + return (Char.IsLetterOrDigit(ch) || idChars.IndexOf(ch) != -1); + } + + /// + /// + /// + public override string Build() + { + if (mode == Token.UNKNOWN) return String.Empty; + int ch = 0; + + ILReader reader = host.Reader; + + StringBuilder idsb = new StringBuilder(); + if (mode == Token.SQSTRING || mode == Token.QSTRING) + { + int term = (mode == Token.SQSTRING) ? '\'' : '"'; + reader.Read(); // skip quote + for (ch = reader.Read(); ch != -1; ch = reader.Read()) + { + if (ch == term) + { + break; + } + + if (ch == '\\') + { + ch = reader.Read(); + + /* + * Long string can be broken across multiple lines + * by using '\' as the last char in line. + * Any white space chars between '\' and the first + * char on the next line are ignored. + */ + if (ch == '\n') + { + reader.SkipWhitespace(); + continue; + } + + int escaped = Escape(reader, ch); + if (escaped == -1) + { + reader.Unread(ch); + ch = '\\'; + } + else + { + ch = escaped; + } + } + + idsb.Append((char) ch); + } + } + else + { + // ID + while ((ch = reader.Read()) != -1) + { + if (IsIdChar(ch)) + { + idsb.Append((char) ch); + } + else + { + reader.Unread(ch); + break; + } + } + } + return idsb.ToString(); + } + + + /// + /// + /// + /// + public static int Escape(ILReader reader, int ch) + { + int res = -1; + + if (ch >= '0' && ch <= '7') + { + StringBuilder octal = new StringBuilder(); + octal.Append((char) ch); + int possibleOctalChar = reader.Peek(); + if (possibleOctalChar >= '0' && possibleOctalChar <= '7') + { + octal.Append((char) reader.Read()); + possibleOctalChar = reader.Peek(); + if (possibleOctalChar >= '0' && possibleOctalChar <= '7') + octal.Append((char) reader.Read()); + } + res = Convert.ToInt32(octal.ToString(), 8); + } + else + { + int id = "abfnrtv\"'\\".IndexOf((char) ch); + if (id != -1) + { + res = "\a\b\f\n\r\t\v\"'\\"[id]; + } + } + + return res; + } + } +} \ No newline at end of file diff --git a/Mono.Assembler/StringHelperBase.cs b/Mono.Assembler/StringHelperBase.cs new file mode 100755 index 0000000..9853200 --- /dev/null +++ b/Mono.Assembler/StringHelperBase.cs @@ -0,0 +1,61 @@ +// StringHelperBase.cs +// Author: Sergey Chaban (serge@wildwestsoftware.com) + +using System; +using System.Text; + +namespace Mono.Assembler +{ + /// + /// + internal abstract class StringHelperBase + { + protected ILTokenizer host; + protected int mode; + + /// + /// + /// + public StringHelperBase(ILTokenizer host) + { + this.host = host; + mode = Token.UNKNOWN; + } + + /// + /// + /// + public abstract bool Start(char ch); + + + /// + /// + /// + public bool Start(int ch) + { + return Start((char) ch); + } + + /// + /// + /// + public bool Start() + { + return Start(host.Reader.Peek()); + } + + + /// + /// + /// + public abstract string Build(); + + + /// + /// + public int TokenId + { + get { return mode; } + } + } +} \ No newline at end of file diff --git a/Mono.Assembler/Token.cs b/Mono.Assembler/Token.cs new file mode 100755 index 0000000..afdd458 --- /dev/null +++ b/Mono.Assembler/Token.cs @@ -0,0 +1,311 @@ +namespace Mono.Assembler +{ + internal class Token + { + public const int EOF = 257; + public const int ID = 258; + public const int QSTRING = 259; + public const int SQSTRING = 260; + public const int COMP_NAME = 261; + public const int INT32 = 262; + public const int INT64 = 263; + public const int FLOAT64 = 264; + public const int HEXBYTE = 265; + public const int DOT = 266; + public const int OPEN_BRACE = 267; + public const int CLOSE_BRACE = 268; + public const int OPEN_BRACKET = 269; + public const int CLOSE_BRACKET = 270; + public const int OPEN_PARENS = 271; + public const int CLOSE_PARENS = 272; + public const int COMMA = 273; + public const int COLON = 274; + public const int DOUBLE_COLON = 275; + public const int SEMICOLON = 277; + public const int ASSIGN = 278; + public const int STAR = 279; + public const int AMPERSAND = 280; + public const int PLUS = 281; + public const int SLASH = 282; + public const int BANG = 283; + public const int ELLIPSIS = 284; + public const int DASH = 286; + public const int OPEN_ANGLE_BRACKET = 287; + public const int CLOSE_ANGLE_BRACKET = 288; + public const int UNKNOWN = 289; + public const int INSTR_NONE = 290; + public const int INSTR_VAR = 291; + public const int INSTR_I = 292; + public const int INSTR_I8 = 293; + public const int INSTR_R = 294; + public const int INSTR_BRTARGET = 295; + public const int INSTR_METHOD = 296; + public const int INSTR_NEWOBJ = 297; + public const int INSTR_FIELD = 298; + public const int INSTR_TYPE = 299; + public const int INSTR_STRING = 300; + public const int INSTR_SIG = 301; + public const int INSTR_RVA = 302; + public const int INSTR_TOK = 303; + public const int INSTR_SWITCH = 304; + public const int INSTR_PHI = 305; + public const int INSTR_LOCAL = 306; + public const int INSTR_PARAM = 307; + public const int D_ADDON = 308; + public const int D_ALGORITHM = 309; + public const int D_ASSEMBLY = 310; + public const int D_BACKING = 311; + public const int D_BLOB = 312; + public const int D_CAPABILITY = 313; + public const int D_CCTOR = 314; + public const int D_CLASS = 315; + public const int D_COMTYPE = 316; + public const int D_CONFIG = 317; + public const int D_IMAGEBASE = 318; + public const int D_CORFLAGS = 319; + public const int D_CTOR = 320; + public const int D_CUSTOM = 321; + public const int D_DATA = 322; + public const int D_EMITBYTE = 323; + public const int D_ENTRYPOINT = 324; + public const int D_EVENT = 325; + public const int D_EXELOC = 326; + public const int D_EXPORT = 327; + public const int D_FIELD = 328; + public const int D_FILE = 329; + public const int D_FIRE = 330; + public const int D_GET = 331; + public const int D_HASH = 332; + public const int D_IMPLICITCOM = 333; + public const int D_LANGUAGE = 334; + public const int D_LINE = 335; + public const int D_XLINE = 336; + public const int D_LOCALE = 337; + public const int D_LOCALS = 338; + public const int D_MANIFESTRES = 339; + public const int D_MAXSTACK = 340; + public const int D_METHOD = 341; + public const int D_MIME = 342; + public const int D_MODULE = 343; + public const int D_MRESOURCE = 344; + public const int D_NAMESPACE = 345; + public const int D_ORIGINATOR = 346; + public const int D_OS = 347; + public const int D_OTHER = 348; + public const int D_OVERRIDE = 349; + public const int D_PACK = 350; + public const int D_PARAM = 351; + public const int D_PERMISSION = 352; + public const int D_PERMISSIONSET = 353; + public const int D_PROCESSOR = 354; + public const int D_PROPERTY = 355; + public const int D_PUBLICKEY = 356; + public const int D_PUBLICKEYTOKEN = 357; + public const int D_REMOVEON = 358; + public const int D_SET = 359; + public const int D_SIZE = 360; + public const int D_STACKRESERVE = 361; + public const int D_SUBSYSTEM = 362; + public const int D_TITLE = 363; + public const int D_TRY = 364; + public const int D_VER = 365; + public const int D_VTABLE = 366; + public const int D_VTENTRY = 367; + public const int D_VTFIXUP = 368; + public const int D_ZEROINIT = 369; + public const int K_AT = 370; + public const int K_AS = 371; + public const int K_IMPLICITCOM = 372; + public const int K_IMPLICITRES = 373; + public const int K_NOAPPDOMAIN = 374; + public const int K_NOPROCESS = 375; + public const int K_NOMACHINE = 376; + public const int K_EXTERN = 377; + public const int K_INSTANCE = 378; + public const int K_EXPLICIT = 379; + public const int K_DEFAULT = 380; + public const int K_VARARG = 381; + public const int K_UNMANAGED = 382; + public const int K_CDECL = 383; + public const int K_STDCALL = 384; + public const int K_THISCALL = 385; + public const int K_FASTCALL = 386; + public const int K_MARSHAL = 387; + public const int K_IN = 388; + public const int K_OUT = 389; + public const int K_OPT = 390; + public const int K_STATIC = 391; + public const int K_PUBLIC = 392; + public const int K_PRIVATE = 393; + public const int K_FAMILY = 394; + public const int K_INITONLY = 395; + public const int K_RTSPECIALNAME = 396; + public const int K_STRICT = 397; + public const int K_SPECIALNAME = 398; + public const int K_ASSEMBLY = 399; + public const int K_FAMANDASSEM = 400; + public const int K_FAMORASSEM = 401; + public const int K_PRIVATESCOPE = 402; + public const int K_LITERAL = 403; + public const int K_NOTSERIALIZED = 404; + public const int K_VALUE = 405; + public const int K_NOT_IN_GC_HEAP = 406; + public const int K_INTERFACE = 407; + public const int K_SEALED = 408; + public const int K_ABSTRACT = 409; + public const int K_AUTO = 410; + public const int K_SEQUENTIAL = 411; + public const int K_ANSI = 412; + public const int K_UNICODE = 413; + public const int K_AUTOCHAR = 414; + public const int K_BESTFIT = 415; + public const int K_IMPORT = 416; + public const int K_SERIALIZABLE = 417; + public const int K_NESTED = 418; + public const int K_LATEINIT = 419; + public const int K_EXTENDS = 420; + public const int K_IMPLEMENTS = 421; + public const int K_FINAL = 422; + public const int K_VIRTUAL = 423; + public const int K_HIDEBYSIG = 424; + public const int K_NEWSLOT = 425; + public const int K_UNMANAGEDEXP = 426; + public const int K_PINVOKEIMPL = 427; + public const int K_NOMANGLE = 428; + public const int K_OLE = 429; + public const int K_LASTERR = 430; + public const int K_WINAPI = 431; + public const int K_NATIVE = 432; + public const int K_IL = 433; + public const int K_CIL = 434; + public const int K_OPTIL = 435; + public const int K_MANAGED = 436; + public const int K_FORWARDREF = 437; + public const int K_RUNTIME = 438; + public const int K_INTERNALCALL = 439; + public const int K_SYNCHRONIZED = 440; + public const int K_NOINLINING = 441; + public const int K_CUSTOM = 442; + public const int K_FIXED = 443; + public const int K_SYSSTRING = 444; + public const int K_ARRAY = 445; + public const int K_VARIANT = 446; + public const int K_CURRENCY = 447; + public const int K_SYSCHAR = 448; + public const int K_VOID = 449; + public const int K_BOOL = 450; + public const int K_INT8 = 451; + public const int K_INT16 = 452; + public const int K_INT32 = 453; + public const int K_INT64 = 454; + public const int K_FLOAT32 = 455; + public const int K_FLOAT64 = 456; + public const int K_ERROR = 457; + public const int K_UNSIGNED = 458; + public const int K_UINT = 459; + public const int K_UINT8 = 460; + public const int K_UINT16 = 461; + public const int K_UINT32 = 462; + public const int K_UINT64 = 463; + public const int K_DECIMAL = 464; + public const int K_DATE = 465; + public const int K_BSTR = 466; + public const int K_LPSTR = 467; + public const int K_LPWSTR = 468; + public const int K_LPTSTR = 469; + public const int K_OBJECTREF = 470; + public const int K_IUNKNOWN = 471; + public const int K_IDISPATCH = 472; + public const int K_STRUCT = 473; + public const int K_SAFEARRAY = 474; + public const int K_INT = 475; + public const int K_BYVALSTR = 476; + public const int K_TBSTR = 477; + public const int K_LPVOID = 478; + public const int K_ANY = 479; + public const int K_FLOAT = 480; + public const int K_LPSTRUCT = 481; + public const int K_NULL = 482; + public const int K_PTR = 483; + public const int K_VECTOR = 484; + public const int K_HRESULT = 485; + public const int K_CARRAY = 486; + public const int K_USERDEFINED = 487; + public const int K_RECORD = 488; + public const int K_FILETIME = 489; + public const int K_BLOB = 490; + public const int K_STREAM = 491; + public const int K_STORAGE = 492; + public const int K_STREAMED_OBJECT = 493; + public const int K_STORED_OBJECT = 494; + public const int K_BLOB_OBJECT = 495; + public const int K_CF = 496; + public const int K_CLSID = 497; + public const int K_METHOD = 498; + public const int K_CLASS = 499; + public const int K_PINNED = 500; + public const int K_MODREQ = 501; + public const int K_MODOPT = 502; + public const int K_TYPEDREF = 503; + public const int K_TYPE = 504; + public const int K_WCHAR = 505; + public const int K_CHAR = 506; + public const int K_FROMUNMANAGED = 507; + public const int K_CALLMOSTDERIVED = 508; + public const int K_BYTEARRAY = 509; + public const int K_WITH = 510; + public const int K_INIT = 511; + public const int K_TO = 512; + public const int K_CATCH = 513; + public const int K_FILTER = 514; + public const int K_FINALLY = 515; + public const int K_FAULT = 516; + public const int K_HANDLER = 517; + public const int K_TLS = 518; + public const int K_FIELD = 519; + public const int K_PROPERTY = 520; + public const int K_REQUEST = 521; + public const int K_DEMAND = 522; + public const int K_ASSERT = 523; + public const int K_DENY = 524; + public const int K_PERMITONLY = 525; + public const int K_LINKCHECK = 526; + public const int K_INHERITCHECK = 527; + public const int K_REQMIN = 528; + public const int K_REQOPT = 529; + public const int K_REQREFUSE = 530; + public const int K_PREJITGRANT = 531; + public const int K_PREJITDENY = 532; + public const int K_NONCASDEMAND = 533; + public const int K_NONCASLINKDEMAND = 534; + public const int K_NONCASINHERITANCE = 535; + public const int K_READONLY = 536; + public const int K_NOMETADATA = 537; + public const int K_ALGORITHM = 538; + public const int K_FULLORIGIN = 539; + public const int K_ENABLEJITTRACKING = 540; + public const int K_DISABLEJITOPTIMIZER = 541; + public const int K_RETARGETABLE = 542; + public const int K_PRESERVESIG = 543; + public const int K_BEFOREFIELDINIT = 544; + public const int K_ALIGNMENT = 545; + public const int K_NULLREF = 546; + public const int K_VALUETYPE = 547; + public const int K_COMPILERCONTROLLED = 548; + public const int K_REQSECOBJ = 549; + public const int K_ENUM = 550; + public const int K_OBJECT = 551; + public const int K_STRING = 552; + public const int K_TRUE = 553; + public const int K_FALSE = 554; + public const int K_IS = 555; + public const int K_ON = 556; + public const int K_OFF = 557; + public const int K_CHARMAPERROR = 558; + + public const int SL_COMMENT = 559; + public const int ML_COMMENT = 560; + + public const int yyErrorCode = 256; + } +} \ No newline at end of file diff --git a/Properties/AssemblyInfo.cs b/Properties/AssemblyInfo.cs new file mode 100755 index 0000000..90f21cf --- /dev/null +++ b/Properties/AssemblyInfo.cs @@ -0,0 +1,17 @@ +using System.Reflection; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; + +[assembly: AssemblyTitle("SyntaxTree.VisualStudio.IL")] +[assembly: AssemblyDescription("")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("")] +[assembly: AssemblyProduct("vsil")] +[assembly: AssemblyCopyright("Copyright (C) 2011 SyntaxTree")] +[assembly: AssemblyTrademark("")] +[assembly: AssemblyCulture("")] + +[assembly: ComVisible(false)] + +[assembly: AssemblyVersion("1.0.0.0")] +[assembly: AssemblyFileVersion("1.0.0.0")] diff --git a/SyntaxTree.VisualStudio.IL.csproj b/SyntaxTree.VisualStudio.IL.csproj new file mode 100755 index 0000000..044da42 --- /dev/null +++ b/SyntaxTree.VisualStudio.IL.csproj @@ -0,0 +1,100 @@ + + + + Debug + AnyCPU + 10.0.20305 + 2.0 + {82b43b9b-a64c-4715-b499-d71e9ca2bd60};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC} + {D4A3A217-3F32-4C5C-B403-64BF4AEEFDCA} + Library + Properties + SyntaxTree.VisualStudio.IL + SyntaxTree.VisualStudio.IL + v4.0 + 512 + false + + + true + full + false + bin\Debug\ + DEBUG;TRACE + prompt + 4 + + + pdbonly + true + bin\Release\ + TRACE + prompt + 4 + + + Program + C:\Program Files (x86)\Microsoft Visual Studio 10.0\Common7\IDE\devenv.exe + /rootsuffix EXP + + + + False + + + + False + + + False + + + False + + + False + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Designer + + + + + + \ No newline at end of file diff --git a/SyntaxTree.VisualStudio.IL.sln b/SyntaxTree.VisualStudio.IL.sln new file mode 100755 index 0000000..c4380c0 --- /dev/null +++ b/SyntaxTree.VisualStudio.IL.sln @@ -0,0 +1,20 @@ + +Microsoft Visual Studio Solution File, Format Version 11.00 +# Visual Studio 2010 +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SyntaxTree.VisualStudio.IL", "SyntaxTree.VisualStudio.IL.csproj", "{D4A3A217-3F32-4C5C-B403-64BF4AEEFDCA}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Any CPU = Debug|Any CPU + Release|Any CPU = Release|Any CPU + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {D4A3A217-3F32-4C5C-B403-64BF4AEEFDCA}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {D4A3A217-3F32-4C5C-B403-64BF4AEEFDCA}.Debug|Any CPU.Build.0 = Debug|Any CPU + {D4A3A217-3F32-4C5C-B403-64BF4AEEFDCA}.Release|Any CPU.ActiveCfg = Release|Any CPU + {D4A3A217-3F32-4C5C-B403-64BF4AEEFDCA}.Release|Any CPU.Build.0 = Release|Any CPU + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection +EndGlobal diff --git a/SyntaxTree.VisualStudio.IL/ILClassifier.cs b/SyntaxTree.VisualStudio.IL/ILClassifier.cs new file mode 100755 index 0000000..f3d1dee --- /dev/null +++ b/SyntaxTree.VisualStudio.IL/ILClassifier.cs @@ -0,0 +1,403 @@ +using System; +using System.Collections.Generic; +using System.Diagnostics; +using System.IO; +using System.Text; +using Microsoft.VisualStudio.Language.StandardClassification; +using Microsoft.VisualStudio.Text; +using Microsoft.VisualStudio.Text.Classification; +using Mono.Assembler; + +namespace SyntaxTree.VisualStudio.IL +{ + internal class ILClassifier : IClassifier + { + private readonly IStandardClassificationService _standardClassificationService; + + internal ILClassifier(IStandardClassificationService standardClassificationService) + { + _standardClassificationService = standardClassificationService; + } + + public IList GetClassificationSpans(SnapshotSpan span) + { + var result = new List(); + var lexer = CreateLexerFor(span.GetText()); + var begin = -1; + var length = -1; + IClassificationType classification = null; + var offset = span.Start.Position; + while (ScanTokenAndProvideInfoAboutIt(lexer, span.GetText(), ref begin, ref length, ref classification)) + { + try + { + result.Add(new ClassificationSpan(new SnapshotSpan(span.Snapshot, offset + begin, length), classification)); + } + catch (Exception e) + { + Debug.WriteLine(e.Message); + break; + } + } + return result; + } + + private bool ScanTokenAndProvideInfoAboutIt(ILTokenizer lexer, string span, ref int begin, ref int length, + ref IClassificationType classification) + { + var location = (Location) lexer.Location.Clone(); + var token = lexer.GetNextToken(); + + switch (token.TokenId) + { + case Token.EOF: + return false; + + case Token.ID: + classification = _standardClassificationService.Identifier; + break; + + case Token.INSTR_NONE: + case Token.INSTR_VAR: + case Token.INSTR_I: + case Token.INSTR_I8: + case Token.INSTR_R: + case Token.INSTR_BRTARGET: + case Token.INSTR_METHOD: + case Token.INSTR_NEWOBJ: + case Token.INSTR_FIELD: + case Token.INSTR_TYPE: + case Token.INSTR_STRING: + case Token.INSTR_SIG: + case Token.INSTR_RVA: + case Token.INSTR_TOK: + case Token.INSTR_SWITCH: + case Token.INSTR_PHI: + case Token.INSTR_LOCAL: + case Token.INSTR_PARAM: + classification = _standardClassificationService.Keyword; + break; + + case Token.K_AT: + case Token.K_AS: + case Token.K_IMPLICITCOM: + case Token.K_IMPLICITRES: + case Token.K_NOAPPDOMAIN: + case Token.K_NOPROCESS: + case Token.K_NOMACHINE: + case Token.K_EXTERN: + case Token.K_INSTANCE: + case Token.K_EXPLICIT: + case Token.K_DEFAULT: + case Token.K_VARARG: + case Token.K_UNMANAGED: + case Token.K_CDECL: + case Token.K_STDCALL: + case Token.K_THISCALL: + case Token.K_FASTCALL: + case Token.K_MARSHAL: + case Token.K_IN: + case Token.K_OUT: + case Token.K_OPT: + case Token.K_STATIC: + case Token.K_PUBLIC: + case Token.K_PRIVATE: + case Token.K_FAMILY: + case Token.K_INITONLY: + case Token.K_RTSPECIALNAME: + case Token.K_STRICT: + case Token.K_SPECIALNAME: + case Token.K_ASSEMBLY: + case Token.K_FAMANDASSEM: + case Token.K_FAMORASSEM: + case Token.K_PRIVATESCOPE: + case Token.K_LITERAL: + case Token.K_NOTSERIALIZED: + case Token.K_VALUE: + case Token.K_NOT_IN_GC_HEAP: + case Token.K_INTERFACE: + case Token.K_SEALED: + case Token.K_ABSTRACT: + case Token.K_AUTO: + case Token.K_SEQUENTIAL: + case Token.K_ANSI: + case Token.K_UNICODE: + case Token.K_AUTOCHAR: + case Token.K_BESTFIT: + case Token.K_IMPORT: + case Token.K_SERIALIZABLE: + case Token.K_NESTED: + case Token.K_LATEINIT: + case Token.K_EXTENDS: + case Token.K_IMPLEMENTS: + case Token.K_FINAL: + case Token.K_VIRTUAL: + case Token.K_HIDEBYSIG: + case Token.K_NEWSLOT: + case Token.K_UNMANAGEDEXP: + case Token.K_PINVOKEIMPL: + case Token.K_NOMANGLE: + case Token.K_OLE: + case Token.K_LASTERR: + case Token.K_WINAPI: + case Token.K_NATIVE: + case Token.K_IL: + case Token.K_CIL: + case Token.K_OPTIL: + case Token.K_MANAGED: + case Token.K_FORWARDREF: + case Token.K_RUNTIME: + case Token.K_INTERNALCALL: + case Token.K_SYNCHRONIZED: + case Token.K_NOINLINING: + case Token.K_CUSTOM: + case Token.K_FIXED: + case Token.K_SYSSTRING: + case Token.K_ARRAY: + case Token.K_VARIANT: + case Token.K_CURRENCY: + case Token.K_SYSCHAR: + case Token.K_VOID: + case Token.K_BOOL: + case Token.K_INT8: + case Token.K_INT16: + case Token.K_INT32: + case Token.K_INT64: + case Token.K_FLOAT32: + case Token.K_FLOAT64: + case Token.K_ERROR: + case Token.K_UNSIGNED: + case Token.K_UINT: + case Token.K_UINT8: + case Token.K_UINT16: + case Token.K_UINT32: + case Token.K_UINT64: + case Token.K_DECIMAL: + case Token.K_DATE: + case Token.K_BSTR: + case Token.K_LPSTR: + case Token.K_LPWSTR: + case Token.K_LPTSTR: + case Token.K_OBJECTREF: + case Token.K_IUNKNOWN: + case Token.K_IDISPATCH: + case Token.K_STRUCT: + case Token.K_SAFEARRAY: + case Token.K_INT: + case Token.K_BYVALSTR: + case Token.K_TBSTR: + case Token.K_LPVOID: + case Token.K_ANY: + case Token.K_FLOAT: + case Token.K_LPSTRUCT: + case Token.K_NULL: + case Token.K_PTR: + case Token.K_VECTOR: + case Token.K_HRESULT: + case Token.K_CARRAY: + case Token.K_USERDEFINED: + case Token.K_RECORD: + case Token.K_FILETIME: + case Token.K_BLOB: + case Token.K_STREAM: + case Token.K_STORAGE: + case Token.K_STREAMED_OBJECT: + case Token.K_STORED_OBJECT: + case Token.K_BLOB_OBJECT: + case Token.K_CF: + case Token.K_CLSID: + case Token.K_METHOD: + case Token.K_CLASS: + case Token.K_PINNED: + case Token.K_MODREQ: + case Token.K_MODOPT: + case Token.K_TYPEDREF: + case Token.K_TYPE: + case Token.K_WCHAR: + case Token.K_CHAR: + case Token.K_FROMUNMANAGED: + case Token.K_CALLMOSTDERIVED: + case Token.K_BYTEARRAY: + case Token.K_WITH: + case Token.K_INIT: + case Token.K_TO: + case Token.K_CATCH: + case Token.K_FILTER: + case Token.K_FINALLY: + case Token.K_FAULT: + case Token.K_HANDLER: + case Token.K_TLS: + case Token.K_FIELD: + case Token.K_PROPERTY: + case Token.K_REQUEST: + case Token.K_DEMAND: + case Token.K_ASSERT: + case Token.K_DENY: + case Token.K_PERMITONLY: + case Token.K_LINKCHECK: + case Token.K_INHERITCHECK: + case Token.K_REQMIN: + case Token.K_REQOPT: + case Token.K_REQREFUSE: + case Token.K_PREJITGRANT: + case Token.K_PREJITDENY: + case Token.K_NONCASDEMAND: + case Token.K_NONCASLINKDEMAND: + case Token.K_NONCASINHERITANCE: + case Token.K_READONLY: + case Token.K_NOMETADATA: + case Token.K_ALGORITHM: + case Token.K_FULLORIGIN: + case Token.K_ENABLEJITTRACKING: + case Token.K_DISABLEJITOPTIMIZER: + case Token.K_RETARGETABLE: + case Token.K_PRESERVESIG: + case Token.K_BEFOREFIELDINIT: + case Token.K_ALIGNMENT: + case Token.K_NULLREF: + case Token.K_VALUETYPE: + case Token.K_COMPILERCONTROLLED: + case Token.K_REQSECOBJ: + case Token.K_ENUM: + case Token.K_OBJECT: + case Token.K_STRING: + case Token.K_TRUE: + case Token.K_FALSE: + case Token.K_IS: + case Token.K_ON: + case Token.K_OFF: + case Token.K_CHARMAPERROR: + classification = _standardClassificationService.Keyword; + break; + + case Token.D_ADDON: + case Token.D_ALGORITHM: + case Token.D_ASSEMBLY: + case Token.D_BACKING: + case Token.D_BLOB: + case Token.D_CAPABILITY: + case Token.D_CCTOR: + case Token.D_CLASS: + case Token.D_COMTYPE: + case Token.D_CONFIG: + case Token.D_IMAGEBASE: + case Token.D_CORFLAGS: + case Token.D_CTOR: + case Token.D_CUSTOM: + case Token.D_DATA: + case Token.D_EMITBYTE: + case Token.D_ENTRYPOINT: + case Token.D_EVENT: + case Token.D_EXELOC: + case Token.D_EXPORT: + case Token.D_FIELD: + case Token.D_FILE: + case Token.D_FIRE: + case Token.D_GET: + case Token.D_HASH: + case Token.D_IMPLICITCOM: + case Token.D_LANGUAGE: + case Token.D_LINE: + case Token.D_XLINE: + case Token.D_LOCALE: + case Token.D_LOCALS: + case Token.D_MANIFESTRES: + case Token.D_MAXSTACK: + case Token.D_METHOD: + case Token.D_MIME: + case Token.D_MODULE: + case Token.D_MRESOURCE: + case Token.D_NAMESPACE: + case Token.D_ORIGINATOR: + case Token.D_OS: + case Token.D_OTHER: + case Token.D_OVERRIDE: + case Token.D_PACK: + case Token.D_PARAM: + case Token.D_PERMISSION: + case Token.D_PERMISSIONSET: + case Token.D_PROCESSOR: + case Token.D_PROPERTY: + case Token.D_PUBLICKEY: + case Token.D_PUBLICKEYTOKEN: + case Token.D_REMOVEON: + case Token.D_SET: + case Token.D_SIZE: + case Token.D_STACKRESERVE: + case Token.D_SUBSYSTEM: + case Token.D_TITLE: + case Token.D_TRY: + case Token.D_VER: + case Token.D_VTABLE: + case Token.D_VTENTRY: + case Token.D_VTFIXUP: + case Token.D_ZEROINIT: + classification = _standardClassificationService.Keyword; + break; + + case Token.INT32: + case Token.INT64: + case Token.FLOAT64: + classification = _standardClassificationService.NumberLiteral; + break; + + case Token.QSTRING: + case Token.SQSTRING: + classification = _standardClassificationService.StringLiteral; + break; + + case Token.SL_COMMENT: + classification = _standardClassificationService.Comment; + break; + + case Token.ML_COMMENT: + classification = _standardClassificationService.Comment; + return true; + + default: + classification = _standardClassificationService.FormalLanguage; + break; + } + + ComputeTokenInfo(span, location, lexer.Location, out begin, out length); + return true; + } + + private void ComputeTokenInfo(string span, Location location, Location nextLocation, out int begin, out int length) + { + begin = location.column - 1; + + if (location.line == nextLocation.line && nextLocation.column != 0) + { + length = nextLocation.column - 1 - begin; + span = span.Substring(begin, length); + } + else + span = span.Substring(begin); + + + var untrimmedLength = span.Length; + span = span.TrimStart(); + + var spanLength = span.Length; + begin += untrimmedLength - spanLength; + length = spanLength; + } + + private ILTokenizer CreateLexerFor(string text) + { + return new ILTokenizer(new StreamReader(StreamFor(text))); + } + + private static MemoryStream StreamFor(string text) + { + var stream = new MemoryStream(); + var bytes = Encoding.UTF8.GetBytes(text); + stream.Write(bytes, 0, bytes.Length); + stream.Position = 0; + return stream; + } + + public event EventHandler ClassificationChanged; + } +} \ No newline at end of file diff --git a/SyntaxTree.VisualStudio.IL/ILClassifierProvider.cs b/SyntaxTree.VisualStudio.IL/ILClassifierProvider.cs new file mode 100755 index 0000000..f2e69b1 --- /dev/null +++ b/SyntaxTree.VisualStudio.IL/ILClassifierProvider.cs @@ -0,0 +1,24 @@ +using System.ComponentModel.Composition; +using Microsoft.VisualStudio.Language.StandardClassification; +using Microsoft.VisualStudio.Text; +using Microsoft.VisualStudio.Text.Classification; +using Microsoft.VisualStudio.Utilities; + +namespace SyntaxTree.VisualStudio.IL +{ + [Export(typeof(IClassifierProvider))] + [ContentType(ILContentDefinition.ILContentType)] + class ILClassifierProvider : IClassifierProvider + { + [Import] + internal IStandardClassificationService StandardClassificationService; + + //[Import] + //internal IClassificationTypeRegistryService ClassificationRegistry; + + public IClassifier GetClassifier(ITextBuffer buffer) + { + return buffer.Properties.GetOrCreateSingletonProperty(() => new ILClassifier(StandardClassificationService)); + } + } +} diff --git a/SyntaxTree.VisualStudio.IL/ILContentDefinition.cs b/SyntaxTree.VisualStudio.IL/ILContentDefinition.cs new file mode 100755 index 0000000..ee229f8 --- /dev/null +++ b/SyntaxTree.VisualStudio.IL/ILContentDefinition.cs @@ -0,0 +1,43 @@ +using System.ComponentModel.Composition; +using System.Windows.Media; +using Microsoft.VisualStudio.Text.Classification; +using Microsoft.VisualStudio.Utilities; + +namespace SyntaxTree.VisualStudio.IL +{ + internal static class ILContentDefinition + { + public const string ILContentType = "IL"; + + [Export] + [Name(ILContentType)] + [BaseDefinition("code")] + internal static ContentTypeDefinition ILContentTypeDefinition; + + [Export] + [FileExtension(".il")] + [ContentType(ILContentType)] + internal static FileExtensionToContentTypeDefinition ILFileExtensionDefinition; + } + + static class ILClassificationDefinitions + { + [Export] + [Name("ILDeclaration")] + internal static ClassificationTypeDefinition ILDeclaration; + } + + [Export(typeof(EditorFormatDefinition))] + [ClassificationType(ClassificationTypeNames = "ILDeclaration")] + [UserVisible(true)] + [Name("ILDeclaration")] + [Order(After = Priority.Default)] + sealed class BooPrimitiveFormat : ClassificationFormatDefinition + { + public BooPrimitiveFormat() + { + DisplayName = "IL - Declaration"; + ForegroundColor = Color.FromArgb(255, 1, 128, 148); + } + } +} diff --git a/source.extension.vsixmanifest b/source.extension.vsixmanifest new file mode 100755 index 0000000..208e08d --- /dev/null +++ b/source.extension.vsixmanifest @@ -0,0 +1,21 @@ + + + + VSIL + SyntaxTree + 1.0 + VisualStudio package to add support for IL files. + 1033 + http://github.com/syntaxtree/vsil + + + Pro + + + + + + + |%CurrentProject%| + +