Exemple #1
0
        void _DeclareFunction()
        {
            //now we expect one of:
            //	function declaration, like TYPE __stdcall Func(TYPE a, TYPE b);
            //	global variable, which can be:
            //		previously-defined type, like TYPE var;
            //		now-defined function type, like TYPE (*var)(TYPE a, TYPE b);


            var d = new _FINDTYPEDATA();

            _FindTypename(false, ref d);
            _i++;

            //pointer
            int ptr = 0;

            while (_TokIsChar(_i, '*', '&'))
            {
                _i++; ptr++;
            }

            if (!_TokIsIdent(_i))
            {
                //could be 'T (*var)(...);' //0 in SDK
                //_Err(_i, "unexpected");
                _SkipStatement(true);
                return;
            }

            int iCallConv = 0;

            if (_TokIsIdent(_i + 1))
            {
                iCallConv = _i++;
            }

            if (!_TokIsChar(_i + 1, '('))
            {
                //could be 'T var;' //1 in SDK
                //_Err(_i, "unexpected");
                _i = d.outTypenameToken;
                if (!_ExternConst())
                {
                    _SkipStatement(true);
                }
                return;
            }

            string name = _TokToString(_i++);

            //skip some
            if (name.IndexOf('_') > 0)
            {
                if (name.Ends("_UserSize") ||
                    name.Ends("_UserMarshal") ||
                    name.Ends("_UserUnmarshal") ||
                    name.Ends("_UserFree") ||
                    name.Ends("_UserSize64") ||
                    name.Ends("_UserMarshal64") ||
                    name.Ends("_UserUnmarshal64") ||
                    name.Ends("_UserFree64")
                    )
                {
                    _SkipStatement(false);
                    return;
                }
            }

            string callConv = iCallConv == 0 ? "Cdecl" : _ConvertCallConv(iCallConv);
            string returnType, returnAttr = null; bool isHRESULT = false;

            if (ptr == 0 && _TokIs(d.outTypenameToken, "HRESULT"))
            {
                isHRESULT  = true;
                returnType = "int";
            }
            else
            {
                returnType = _ConvertTypeName(d.outSym, ref ptr, d.outIsConst, d.outTypenameToken, _TypeContext.Return, out returnAttr);
            }

            string dll, nameInDll = null;

            if (_funcDllMap.TryGetValue(name, out dll))
            {
                int i = dll.IndexOf('|');
                if (i > 0)
                {
                    nameInDll = dll.Substring(i + 1);
                    dll       = dll.Substring(0, i);
                    //AOutput.Write(nameInDll);
                }
                else if (name.Starts("K32"))
                {
                    //AOutput.Write(name);
                    nameInDll = name;
                    name      = name.Substring(3);
                    if (name.Ends("W"))
                    {
                        name = name.Remove(name.Length - 1);
                    }
                    else if (name.Ends("A"))
                    {
                        _SkipStatement(false);
                        return;
                    }
                }
            }
            else
            {
                bool skip = false;
                if (name.Contains("_"))
                {
                    skip = true;                                    //mostly CRT library functions, X_Proxy/X_Stub, X_UserMarshal and similar
                }
                else if (name.Starts("Dll"))
                {
                    skip = true;                                         //DllInstall, DllRegisterServer etc
                }
                else if (name.Starts("Ndr") || name.Starts("Rpc"))
                {
                    skip = true;                                                               //undocumented
                }
                else
                {
                    //AOutput.Write(name);
                    skip = true;                     //all these in SDK others are undocumented, or documented as deprecated/removed
                    _funcUnknownDll.Add(name);
                }

                if (skip)
                {
                    _SkipStatement();
                    return;
                }
                dll = "?";
            }

            var sb = _sbFuncTemp;

            sb.Clear();
            sb.Append("\r\n[DllImport(\"");
            sb.Append(dll);
            sb.Append('\"');
            if (nameInDll != null)
            {
                sb.AppendFormat(", EntryPoint=\"{0}\"", nameInDll);
            }
            if (callConv != null)
            {
                sb.AppendFormat(", CallingConvention=CallingConvention.{0}", callConv);
            }
            if (isHRESULT)
            {
                sb.Append(", PreserveSig=true");                       //default, but makes clear that it returns HRESULT and easier to change to 'false'
            }
            sb.AppendLine(")]");
            if (returnAttr != null)
            {
                sb.AppendLine(returnAttr);
            }
            sb.Append("internal static extern ");
            sb.Append(returnType);
            sb.Append(' ');
            sb.Append(name);

            _ConvertParameters(sb, name, _TypeContext.Parameter);

            string decl = sb.ToString();

            _func[name] = decl;
            //try { _func.Add(name, decl); }
            //catch { //about 10 in SDK. The second declarations are identical or better (without tagSTRUCT).
            //	AOutput.Write("----");
            //	AOutput.Write(name);
            //	AOutput.Write(_func[name]);
            //	AOutput.Write(decl);
            //}

            if (!_TokIsChar(_i, ';'))
            {
                _Err(_i, "unexpected");
            }
        }
Exemple #2
0
        /// <summary>
        /// Converts C++ function parameter or struct member definition (type, name, const etc) to C# typename/name/etc.
        /// _i must be at its start. Finally it will be after the parsed part. Does not check whether it is followed by ',' etc.
        /// </summary>
        /// <param name="context">Member, Parameter or DelegateParameter.</param>
        /// <param name="t">Receives C# typename, name etc.</param>
        /// <param name="parentName">The function/struct name. Used to auto-create names for nameless parameters.</param>
        /// <param name="iParam">1-based index of parameter/member. Used to auto-create names for nameless parameters.</param>
        void _ParseParamOrMember(_TypeContext context, out _PARAMDATA t, string parentName, int iParam)
        {
            bool isMember = context == _TypeContext.Member;

            t = new _PARAMDATA();

            int iSAL = 0;

            if (_TokIsChar(_i, '^') && _TokIsChar(_i + 1, '\"'))
            {
                _i++;
                if (!isMember)
                {
                    iSAL       = _i;
                    _tok[iSAL] = new _Token(_tok[iSAL].s + 1, _tok[iSAL].len - 2);
                }
                _i++;
            }

            var d = new _FINDTYPEDATA();

            _FindTypename(isMember, ref d);
            if (d.outIsNestedTypeDefinition)
            {
                if (_TokIsChar(_i, ';'))
                {
                    t.isNestedTypeDefinitionWithoutVariables    = true;
                    t.isAnonymousTypeDefinitionWithoutVariables = d.outIsAnonymousTypeDefinition;
                    t.typeName = d.outSym.csTypename;
                    return;
                }
            }
            else
            {
                _i++;
            }

            //pointer
            int ptr = 0;

            while (_TokIsChar(_i, '*', '&'))
            {
                _i++; ptr++;
            }

            //suport inline function type definition
            bool isFunc = !d.outIsNestedTypeDefinition && _DetectIsFuncType(_i);

            if (isFunc)
            {
                var f = new _INLINEFUNCTYPEDATA(parentName, iParam);
                _DeclareTypedefFunc(d.outSym, ptr, d.outIsConst, d.outTypenameToken, f);
                t.typeName = f.typeName;
                t.name     = f.paramName;
            }
            else
            {
                //typename, param/member name
                t.typeName = _ConvertTypeName(d.outSym, ref ptr, d.outIsConst, d.outTypenameToken, context, out t.attributes, iSAL);

                if (_TokIsIdent(_i))
                {
                    t.name = _TokToString(_i++);
                }
                else if (!isMember && _TokIsChar(_i, ",)[="))
                {
                    t.name = "param" + iParam;
                }
                else
                {
                    _Err(_i, "no name");
                }
            }

            if (_TokIsChar(_i, '['))
            {
                _ConvertCArray(ref t.typeName, ref t.name, ref t.attributes, !isMember);
            }

            //escape names that are C# keywords
            if (_csKeywords.Contains(t.name))
            {
                //AOutput.Write(t.name);
                t.name = "@" + t.name;
            }
        }
Exemple #3
0
        /// <summary>
        /// Finds typename. Gets its _Symbol etc.
        /// Starts searching from _i. Finally _i will be typename token index.
        /// Error if not found.
        /// Initially sets all outX=0/false/null.
        /// If there is 'const', sets outIsConst=true.
        /// If there is 'struct' etc as nested definition, converts the definition, sets outIsNestedStruct=true; then _i finally will be after }, which can be semicolon, variable name or * variable name.
        /// If there is 'struct' etc as forward declaration, adds forward declaration.
        /// </summary>
        void _FindTypename(bool isMember, ref _FINDTYPEDATA d)
        {
            d.outSym     = null;
            d.outIsConst = false;
            d.outIsNestedTypeDefinition = false;
            d.outTypenameToken          = 0;

            //process keywords until typename
            for (; _TokIsIdent(_i); _i++)
            {
                d.outSym = _FindSymbol(_i, true);
                var k = d.outSym as _Keyword;
                if (k == null)
                {
                    d.outTypenameToken = _i;
                    return;
                }

                switch (k.kwType)
                {
                case _KeywordT.TypeDecl:
                    //is nested struct/enum/typedef definition?
                    if (isMember)
                    {
                        bool isDef = false;
                        if (_TokIsChar(_i, 't'))
                        {
                            isDef = true;
                        }
                        else
                        {
                            int j = _i + 1; if (_TokIsIdent(j))
                            {
                                j++;
                            }
                            if (_TokIsChar(j, "{:;"))
                            {
                                isDef = true;
                            }
                        }
                        if (isDef)
                        {
                            _DeclareType(ref d);
                            d.outIsNestedTypeDefinition = true;
                            return;
                        }
                    }

                    //inline forward declaration
                    d.outSym           = _InlineForwardDeclaration();
                    d.outTypenameToken = _i;
                    return;

                case _KeywordT.Normal:
                    if (_TokIs(_i, "const"))
                    {
                        d.outIsConst = true; continue;
                    }
                    break;
                }

                _Err(_i, "unexpected");
            }
            _Err(_i, "no type");
        }
Exemple #4
0
        void _Statement()
        {
            //try {
g0:
            _Symbol x = _FindSymbol(_i, true);
            var k = x as _Keyword;

            if (k != null)
            {
                if (k.cannotStartStatement)
                {
                    _Err(_i, "unexpected");
                }

                if (k.kwType == _KeywordT.TypeDecl)
                {
                    //is forward decl like 'struct X* Func(...);'?
                    if (!_TokIsChar(_i, 't') && _TokIsChar(_i + 2, '*', '&'))
                    {
                        _InlineForwardDeclaration();
                        goto g0;
                    }

                    var ftd = new _FINDTYPEDATA();                     //just for ref parameter
                    _DeclareType(ref ftd, true);
                }
                else if (k.kwType == _KeywordT.IgnoreFuncEtc)
                {
                    _SkipStatement();
                    return;
                }
                else if (_TokIs(_i, "extern"))
                {
                    if (_TokIsChar(_i + 1, '\"'))                      //extern "C"
                    {
                        _i++;
                        if (_TokIsChar(_i + 1, '{'))
                        {
                            _i++;
                        }
                        return;
                    }
                    else                         //extern T X
                    {
                        if (_TokIs(++_i, "const"))
                        {
                            _i++;
                        }
                        if (!_ExternConst())
                        {
                            _SkipStatement();
                        }
                    }
                }
                else if (_TokIs(_i, "const"))
                {
                    _i++;
                    if (!_ExternConst(true))
                    {
                        _SkipStatement();
                    }
                }
                else
                {
                    //can be:
                    //namespace

                    _Err(_i, "unexpected");                     //TODO
                }
                if (!_TokIsChar(_i, ';'))
                {
                    _Err(_i, "unexpected");
                }
            }
            else                 //a type
            {
                _DeclareFunction();
            }
            //}
            //catch(ConverterException e) {
            //	//AOutput.Write(e);
            //	AWnd.FindFast(null, "QM_Editor").SendS(Api.WM_SETTEXT, 1, $"M \"api_converter_error\" A(||) {e.Message}||{_cppFile}||{e.Offset}");
            //	if(ADialog.Show("Error. Skip statement and continue?", e.Message, "Yes|No").ButtonName != "Yes") throw e as Exception;
            //	_SkipStatement();
            //         }
        }