bool _ExternConst(bool isJustConst = false) { if (!(_TokIsIdent(_i) && _TokIsIdent(_i + 1))) { return(false); //must be TYPE name } int what = 0; if (_TokIsChar(_i + 2, ';')) { what = 1; } else if (isJustConst && _TokIsChar(_i + 2, '=')) { what = 2; } else { return(false); } //get type _Symbol x; if (!_TryFindSymbol(_i, out x, false)) { return(false); } if (0 != _Unalias(_i, ref x)) { return(false); } _i++; if (what == 1) { //we need only GUID if (x.csTypename != "GUID") { return(false); } string name = _TokToString(_i), data; if (!_guids.TryGetValue(name, out data)) { //AOutput.Write(name); return(false); } if (name.Ends("A") && char.IsLower(name[name.Length - 2])) { //AOutput.Write(name); return(false); } else if (name.Ends("W") && char.IsLower(name[name.Length - 2])) { //AOutput.Write(name); name = name.Remove(name.Length - 1); } if (!_guidsAdded.Add(name)) { return(false); //prevent duplicates } _sbVar.AppendFormat("\r\ninternal static Guid {0} = new Guid({1});\r\n", name, data); _i++; } else //C++ const constant { var ct = x as _CppType; if (ct == null) { //_Err(_i, "example"); return(false); } int iName = _i++, iValue = ++_i; while (!_TokIsChar(_i, ';')) { _i++; } string name = _TokToString(iName); _ExpressionResult r = _Expression(iValue, _i, name); //OutList(ct.csTypename, r.typeS, r.valueS); if (r.typeS == null) { return(false); } _enumValues[_tok[iName]] = r.valueI; __sbDef.Clear(); __sbDef.AppendFormat("internal const {0} {1} = {2};", ct.csTypename, name, r.valueS); //AOutput.Write(__sbDef); _cppConst.Add(__sbDef.ToString()); } return(true); }
/// <summary> /// Converts C-style fixed-size array to C#. Gets MarshalAs attribute, appends "[]" to typeName etc. /// Supports "[y][x]" etc. /// _i must be at '['. Finally it will be after ']'. /// If empty array (like TYPE x[] or TYPE x[0]), attributes receives "//...". If 1-element array, receives "/*...*/". /// </summary> /// <param name="typeName">This function appends "[]" if need, or convertes "char" to "string".</param> /// <param name="memberName">If less than 8 elements, and memberName looks like a "Reserved" etc, splits into multiple members like "Reserved_0, Reserved_1, ...".</param> /// <param name="attributes">If !isParameter, receives attribute like "[MarshalAs(UnmanagedType.ByValArray, SizeConst = {x})]". If already is MarshalAs attribute, uses it as ArraySubType.</param> /// <param name="isParameter">Just skip [..] or [...][...] and append "[]" to typeName. Used for parameters, because the attribute can be used only with struct fields; C++ arguments for parameters 'TYPE param[n]' are passed like 'TYPE* param', and n is ignored, can be empty.</param> void _ConvertCArray(ref string typeName, ref string memberName, ref string attributes, bool isParameter = false) { uint elemCount = 1; for (; _TokIsChar(_i, '['); _i++) //support [a][b] { int i0 = _i + 1; _SkipEnclosed(); if (isParameter) { continue; } uint ec = 0; if (_i > i0) //else TYPE x[] { _ExpressionResult r = _Expression(i0, _i, "[]"); switch (r.typeS) { case "int": case "uint": break; default: _Err(i0, "cannot calculate"); break; } ec = r.valueI; } elemCount *= ec; } if (isParameter) { typeName += "[]"; return; } if (typeName.Ends("[]")) { typeName = typeName.Remove(typeName.Length - 2); //'TYPE a[n], b[m]' } string marshalAs = "ByValArray", comment = null, comment2 = null; if (elemCount == 0) //variable-length array of >= 0 elements { comment = "//"; //disable the attribute together with member, and let the member be not array } else if (elemCount == 1) //variable-length array of >= 1 elements { comment = "/*"; comment2 = "*/"; //disable the attribute, and let the member be not array } else if (typeName == "char") { typeName = "string"; marshalAs = "ByValTStr"; } else { if (elemCount < 8 && (memberName.Find("Reserved", true) >= 0 || memberName.Find("pad", true) >= 0 || memberName.Starts("Spare", true))) { //AOutput.Write(memberName); var sb = new StringBuilder(); for (int i = 0; i < elemCount; i++) { if (i > 0) { sb.Append(", "); } sb.Append(memberName); sb.Append('_'); sb.Append(i); } memberName = sb.ToString(); comment = "/*"; comment2 = "*/"; } else { //if(elemCount<8) AOutput.Write(memberName); typeName += "[]"; } } if (attributes != null) { _Err(_i, "TODO"); //0 in SDK. Should extract its type from [MarshalAs(UnmanagedType.(\w+) and insert in the new attributes. } attributes = $"{comment}[MarshalAs(UnmanagedType.{marshalAs}, SizeConst = {elemCount})]{comment2}"; }
void _DefineUndef() { char *s = T(++_i); char c = *s; //was like `d$$$_REALNAME, now s is without ` if (c == 'c') //`cx "C# code converted by the preprocessor script", where x tells what it is { if (!_TokIsChar(++_i, '\x2')) { _Err(_i, "unexpected 1"); } _tok[_i] = new _Token(T(_i) + 1, _tok[_i].len - 2); if (s[1] == 'p') { _sbVar.AppendLine(_TokToString(_i)); } else { _Err(_i - 1, "unexpected 2"); } return; } s += 5; int lenName = _tok[_i].len - 5; //skip prefix 'd$$$_' that was added to avoid unexpanding names _tok[_i] = new _Token(s, lenName); int iName = _i; //is function-style? char *s2 = T(++_i); bool isFunc = c == 'd' && *s2 == '(' && s2 == s + lenName; //find value int iValue = _i, iParamOrValue = _i; if (isFunc) { iValue = _SkipEnclosed(_i) + 1; //name(parameters)[ value] } //find next line int iNext = iValue; for (; ; iNext++) { char k = *T(iNext); if (k == '`' || k == '\x0') { break; } } string name = new string(s, 0, lenName); if (c == 'u') //#undef { if (!_defineConst.Remove(name) && !_defineOther.Remove(name)) { _defineW.Remove(name); } //AOutput.Write($"#undef {name}"); } else if (iValue < iNext) //preprocessor removes some #define values, it's ok { if (isFunc) //info: for func-style get parameters as part of value { __DefineAddToOther(iName, name, _TokToString(iParamOrValue, iNext)); } else if (*s2 == '\x2') //ANSI string constant, when tokenizing replaced the first '\"' to '\x2' { *s2 = '\"'; __DefineAddToOther(iName, name, " " + _TokToString(iParamOrValue, iNext) + " //ANSI string"); } else { _ExpressionResult r = _Expression(iParamOrValue, iNext, name); if (r.typeS == null) { bool isFuncWA = (iNext - iValue == 1) && __DefineWA(name, r.valueS); if (!isFuncWA) { //don't add '#define NAME1 NAME2' if (iNext - iValue == 1 && _TokIsIdent(iValue)) { //OutList(name, r.valueS); } else { //OutList(name, iNext-iValue); __DefineAddToOther(iName, name, " " + r.valueS); } } } else { __sbDef.Clear(); __sbDef.AppendFormat("internal {2} {3} {0} = {1};", name, r.valueS, r.notConst ? "readonly" : "const", r.typeS); _defineConst[name] = __sbDef.ToString(); } } } _i = iNext - 1; }