var.h 37 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955
  1. /*
  2. AutoHotkey
  3. Copyright 2003-2009 Chris Mallett (support@autohotkey.com)
  4. This program is free software; you can redistribute it and/or
  5. modify it under the terms of the GNU General Public License
  6. as published by the Free Software Foundation; either version 2
  7. of the License, or (at your option) any later version.
  8. This program is distributed in the hope that it will be useful,
  9. but WITHOUT ANY WARRANTY; without even the implied warranty of
  10. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  11. GNU General Public License for more details.
  12. */
  13. #ifndef var_h
  14. #define var_h
  15. #include "defines.h"
  16. #include "SimpleHeap.h"
  17. #include "clipboard.h"
  18. #include "util.h" // for strlcpy() & snprintf()
  19. EXTERN_CLIPBOARD;
  20. #define MAX_ALLOC_SIMPLE 64 // Do not decrease this much since it is used for the sizing of some built-in variables.
  21. #define SMALL_STRING_LENGTH (MAX_ALLOC_SIMPLE - 1) // The largest string that can fit in the above.
  22. #define DEREF_BUF_EXPAND_INCREMENT (16 * 1024) // Reduced from 32 to 16 in v1.0.46.07 to reduce the memory utilization of deeply recursive UDFs.
  23. enum AllocMethod {ALLOC_NONE, ALLOC_SIMPLE, ALLOC_MALLOC, ALLOC_DISABLED};
  24. enum VarTypes
  25. {
  26. // The following must all be LOW numbers to avoid any realistic chance of them matching the address of
  27. // any function (namely a BIV_* function).
  28. VAR_ALIAS // VAR_ALIAS must always have a non-NULL mAliasFor. In other ways it's the same as VAR_NORMAL. VAR_ALIAS is never seen because external users call Var::Type(), which automatically resolves ALIAS to some other type.
  29. , VAR_NORMAL // Most variables, such as those created by the user, are this type.
  30. , VAR_CONSTANT // or as I like to say, not variable.
  31. , VAR_VIRTUAL
  32. , VAR_VIRTUAL_OBJ
  33. // If adding to this enum, ensure range checks and VAR_LAST_TYPE remain valid.
  34. , VAR_LAST_TYPE = VAR_VIRTUAL_OBJ
  35. };
  36. // Returns true if the given var type should be evaluated by calling Var::Get(ResultToken&).
  37. inline bool VarTypeIsVirtual(int type) { return type >= VAR_VIRTUAL; }
  38. typedef UCHAR VarTypeType; // UCHAR vs. VarTypes to save memory.
  39. typedef UCHAR AllocMethodType; // UCHAR vs. AllocMethod to save memory.
  40. typedef UCHAR VarAttribType; // Same.
  41. typedef UINT_PTR VarSizeType; // jackieku(2009-10-23): Change this to UINT_PTR to ensure its size is the same with a pointer.
  42. #define VARSIZE_MAX ((VarSizeType) ~0)
  43. #define VARSIZE_ERROR VARSIZE_MAX
  44. class Var; // Forward declaration.
  45. // #pragma pack(4) not used here because although it would currently save 4 bytes per VarBkp struct (28 vs. 32),
  46. // it would probably reduce performance since VarBkp items are stored in contiguous array rather than a
  47. // linked list (which would cause every other struct in the array to have an 8-byte member than stretches
  48. // across two 8-byte regions in memory).
  49. struct VarBkp // This should be kept in sync with any changes to the Var class. See Var for comments.
  50. {
  51. union
  52. {
  53. __int64 mContentsInt64; // 64-bit members kept at the top of the struct to reduce the chance that they'll span 2 vs. 1 64-bit regions.
  54. double mContentsDouble;
  55. IObject *mObject;
  56. };
  57. Var *mVar; // Used to save the target var to which these backed up contents will later be restored.
  58. union
  59. {
  60. char *mByteContents;
  61. TCHAR *mCharContents;
  62. };
  63. union
  64. {
  65. VarSizeType mByteLength;
  66. Var *mAliasFor;
  67. };
  68. VarSizeType mByteCapacity;
  69. AllocMethodType mHowAllocated;
  70. VarAttribType mAttrib;
  71. VarTypeType mType;
  72. // Not needed in the backup:
  73. //bool mIsLocal;
  74. //TCHAR *mName;
  75. void ToToken(ExprTokenType &aValue);
  76. };
  77. #define BIV_DECL_R(name) void name(ResultToken &aResultToken, LPTSTR aVarName)
  78. #define BIV_DECL_W(name) void name(ResultToken &aResultToken, LPTSTR aVarName, ExprTokenType &aValue)
  79. #define BIV_DECL_RW(name) BIV_DECL_R(name); BIV_DECL_W(name##_Set)
  80. struct VirtualVar
  81. {
  82. typedef BIV_DECL_R((* Getter));
  83. typedef BIV_DECL_W((* Setter));
  84. Getter Get;
  85. Setter Set;
  86. };
  87. struct VarEntry
  88. {
  89. LPTSTR name;
  90. VirtualVar type;
  91. };
  92. class VarRef;
  93. #pragma warning(push)
  94. #pragma warning(disable: 4995 4996)
  95. // Concerning "#pragma pack" below:
  96. // Default pack would otherwise be 8, which would cause the 64-bit mContentsInt64 member to increase the size
  97. // of the struct from 20 to 32 (instead of 28). Benchmarking indicates that there's no significant performance
  98. // loss from doing this, perhaps because variables are currently stored in a linked list rather than an
  99. // array. (In an array, having the struct size be a multiple of 8 would prevent every other struct in the array
  100. // from having its 64-bit members span more than one 64-bit region in memory, which might reduce performance.)
  101. #ifdef _WIN64
  102. #pragma pack(push, 8)
  103. #else
  104. #pragma pack(push, 4) // 32-bit vs. 64-bit. See above.
  105. #endif
  106. class Var
  107. {
  108. private:
  109. // Keep VarBkp (above) in sync with any changes made to the members here.
  110. union // 64-bit members kept at the top of the struct to reduce the chance that they'll span 2 64-bit regions.
  111. {
  112. // Although the 8-byte members mContentsInt64 and mContentsDouble could be hung onto the struct
  113. // via a 4-byte-pointer, thus saving 4 bytes for each variable that never uses a binary number,
  114. // it doesn't seem worth it because the percentage of variables in typical scripts that will
  115. // acquire a cached binary number at some point seems likely to be high. A percentage of only
  116. // 50% would be enough to negate the savings because half the variables would consume 12 bytes
  117. // more than the version of AutoHotkey that has no binary-number caching, and the other half
  118. // would consume 4 more (due to the unused/empty pointer). That would be an average of 8 bytes
  119. // extra; i.e. exactly the same as the 8 bytes used by putting the numbers directly into the struct.
  120. // In addition, there are the following advantages:
  121. // 1) Code less complicated, more maintainable, faster.
  122. // 2) Caching of binary numbers works even in recursive script functions. By contrast, if the
  123. // binary number were allocated on demand, recursive functions couldn't use caching because the
  124. // memory from SimpleHeap could never be freed, thus producing a memory leak.
  125. // The main drawback is that some scripts are known to create a million variables or more, so the
  126. // extra 8 bytes per variable would increase memory load by 8+ MB (possibly with a boost in
  127. // performance if those variables are ever numeric).
  128. __int64 mContentsInt64;
  129. double mContentsDouble;
  130. IObject *mObject; // L31
  131. VirtualVar *mVV; // VAR_VIRTUAL
  132. };
  133. union
  134. {
  135. LPTSTR mCharContents = sEmptyString; // Invariant: Anyone setting mByteCapacity to 0 must also set mCharContents to the empty string.
  136. char *mByteContents;
  137. };
  138. union
  139. {
  140. Var *mAliasFor = nullptr; // The variable for which this variable is an alias.
  141. VarSizeType mByteLength; // How much is actually stored in it currently, excluding the zero terminator.
  142. };
  143. VarSizeType mByteCapacity = 0; // In bytes. Includes the space for the zero terminator.
  144. AllocMethodType mHowAllocated = ALLOC_NONE; // Keep adjacent/contiguous with the below to save memory.
  145. #define VAR_ATTRIB_CONTENTS_OUT_OF_DATE 0x01 // Combined with VAR_ATTRIB_IS_INT64/DOUBLE/OBJECT to indicate mContents is not current.
  146. #define VAR_ATTRIB_ALREADY_WARNED 0x01 // Combined with VAR_ATTRIB_UNINITIALIZED to limit VarUnset warnings to 1 MsgBox per var. See WarnUnassignedVar.
  147. #define VAR_ATTRIB_UNINITIALIZED 0x02 // Var requires initialization before use.
  148. #define VAR_ATTRIB_HAS_ASSIGNMENT 0x04 // Used during load time to detect vars that are not assigned anywhere.
  149. #define VAR_ATTRIB_NOT_NUMERIC 0x08 // A prior call to IsNumeric() determined the var's value is PURE_NOT_NUMERIC.
  150. #define VAR_ATTRIB_IS_INT64 0x10 // Var's proper value is in mContentsInt64.
  151. #define VAR_ATTRIB_IS_DOUBLE 0x20 // Var's proper value is in mContentsDouble.
  152. #define VAR_ATTRIB_IS_OBJECT 0x40 // Var's proper value is in mObject.
  153. #define VAR_ATTRIB_VIRTUAL_OPEN 0x80 // Virtual var is open for writing.
  154. #define VAR_ATTRIB_CACHE (VAR_ATTRIB_IS_INT64 | VAR_ATTRIB_IS_DOUBLE | VAR_ATTRIB_NOT_NUMERIC) // These three are mutually exclusive.
  155. #define VAR_ATTRIB_TYPES (VAR_ATTRIB_IS_INT64 | VAR_ATTRIB_IS_DOUBLE | VAR_ATTRIB_IS_OBJECT) // These are mutually exclusive (but NOT_NUMERIC may be combined with OBJECT).
  156. #define VAR_ATTRIB_OFTEN_REMOVED (VAR_ATTRIB_CACHE | VAR_ATTRIB_CONTENTS_OUT_OF_DATE | VAR_ATTRIB_UNINITIALIZED)
  157. VarAttribType mAttrib; // Bitwise combination of the above flags (but many of them may be mutually exclusive).
  158. #define VAR_GLOBAL 0x01
  159. #define VAR_LOCAL 0x02
  160. #define VAR_VARREF 0x04 // This is a VarRef (used to determine whether the ToReturnValue optimization is safe).
  161. #define VAR_DOWNVAR 0x08 // This var is captured by a nested function/closure (it's in Func::mDownVar).
  162. #define VAR_LOCAL_FUNCPARAM 0x10 // Indicates this local var is a function's parameter. VAR_LOCAL_DECLARED should also be set.
  163. #define VAR_LOCAL_STATIC 0x20 // Indicates this local var retains its value between function calls.
  164. #define VAR_DECLARED 0x40 // Indicates this var was declared somehow, not automatic.
  165. #define VAR_EXPORTED 0x80 // Exported from a module.
  166. UCHAR mScope; // Bitwise combination of the above flags.
  167. VarTypeType mType; // Keep adjacent/contiguous with the above due to struct alignment, to save memory.
  168. // Performance: Rearranging mType and the other byte-sized members with respect to each other didn't seem
  169. // to help performance. However, changing VarTypeType from UCHAR to int did boost performance a few percent,
  170. // but even if it's not a fluke, it doesn't seem worth the increase in memory for scripts with many
  171. // thousands of variables.
  172. #ifdef CONFIG_DEBUGGER
  173. friend class Debugger;
  174. #endif
  175. // Caller has verified mType == VAR_VIRTUAL.
  176. bool HasSetter() { return mVV->Set; }
  177. // Caller has verified VarTypeIsVirtual(mType).
  178. ResultType AssignVirtual(ExprTokenType &aValue);
  179. // Unconditionally accepts new memory, bypassing the usual redirection to Assign() for VAR_VIRTUAL.
  180. void _AcceptNewMem(LPTSTR aNewMem, VarSizeType aLength);
  181. ResultType AssignBinaryNumber(__int64 aNumberAsInt64, VarAttribType aAttrib = VAR_ATTRIB_IS_INT64);
  182. void UpdateContents()
  183. {
  184. ASSERT(mType != VAR_ALIAS); // Caller has already resolved aliases.
  185. if (mAttrib & VAR_ATTRIB_CONTENTS_OUT_OF_DATE)
  186. {
  187. // THE FOLLOWING ISN'T NECESSARY BECAUSE THE ASSIGN() CALLS BELOW DO IT:
  188. //mAttrib &= ~VAR_ATTRIB_CONTENTS_OUT_OF_DATE;
  189. TCHAR value_string[MAX_NUMBER_SIZE];
  190. if (mAttrib & VAR_ATTRIB_IS_INT64)
  191. {
  192. Assign(ITOA64(mContentsInt64, value_string)); // Return value currently not checked for this or the below.
  193. mAttrib |= VAR_ATTRIB_IS_INT64; // Re-enable the cache because Assign() disables it (since all other callers want that).
  194. }
  195. else if (mAttrib & VAR_ATTRIB_IS_DOUBLE)
  196. {
  197. Assign(value_string, FTOA(mContentsDouble, value_string, _countof(value_string)));
  198. mAttrib |= VAR_ATTRIB_IS_DOUBLE; // Re-enable the cache because Assign() disables it (since all other callers want that).
  199. }
  200. //else nothing to update, which shouldn't happen in this block unless there's a flaw or bug somewhere.
  201. }
  202. }
  203. void _SetObject(IObject *aObject)
  204. {
  205. mObject = aObject;
  206. // Mark this variable to indicate it contains an object (objects are never considered numeric).
  207. mAttrib |= VAR_ATTRIB_IS_OBJECT | VAR_ATTRIB_NOT_NUMERIC;
  208. }
  209. VarSizeType _CharLength() { return mByteLength / sizeof(TCHAR); }
  210. VarSizeType _CharCapacity() { return mByteCapacity / sizeof(TCHAR); }
  211. public:
  212. // Testing shows that due to data alignment, keeping mType adjacent to the other less-than-4-size member
  213. // above it reduces size of each object by 4 bytes.
  214. TCHAR *mName; // The name of the var.
  215. // sEmptyString is a special *writable* memory area for empty variables (those with zero capacity).
  216. // Although making it writable does make buffer overflows difficult to detect and analyze (since they
  217. // tend to corrupt the program's static memory pool), the advantages in maintainability and robustness
  218. // seem to far outweigh that. For example, it avoids having to constantly think about whether
  219. // *Contents()='\0' is safe. The sheer number of places that's avoided is a great relief, and it also
  220. // cuts down on code size due to not having to always check Capacity() and/or create more functions to
  221. // protect from writing to read-only strings, which would hurt performance.
  222. // The biggest offender of buffer overflow in sEmptyString is DllCall, which happens most frequently
  223. // when a script forgets to call VarSetStrCapacity before passing a buffer to some function that writes a
  224. // string to it. There is now some code there that tries to detect when that happens.
  225. static TCHAR sEmptyString[1]; // See above.
  226. void Get(ResultToken &aResultToken);
  227. ResultType AssignHWND(HWND aWnd);
  228. ResultType Assign(Var &aVar);
  229. ResultType Assign(ExprTokenType &aToken);
  230. static void AssignVirtualObj(IObject *aObj, ExprTokenType &aValue, ResultToken &aResultToken);
  231. static ResultType GetClipboardAll(void **aData, size_t *aDataSize);
  232. static ResultType SetClipboardAll(void *aData, size_t aDataSize);
  233. // Assign(char *, ...) has been break into four methods below.
  234. // This should prevent some mistakes, as characters and bytes are not interchangeable in the Unicode build.
  235. // Callers must make sure which one is the right method to call.
  236. ResultType AssignString(LPCTSTR aBuf = NULL, VarSizeType aLength = VARSIZE_MAX, bool aExactSize = false);
  237. inline ResultType Assign(LPCTSTR aBuf, VarSizeType aLength = VARSIZE_MAX, bool aExactSize = false)
  238. {
  239. ASSERT(aBuf); // aBuf shouldn't be NULL, use SetCapacity([length in bytes]) or AssignString(NULL, [length in characters]) instead.
  240. return AssignString(aBuf, aLength, aExactSize);
  241. }
  242. inline ResultType Assign()
  243. {
  244. return AssignString();
  245. }
  246. ResultType SetCapacity(VarSizeType aByteLength, bool aExactSize = false)
  247. {
  248. #ifdef UNICODE
  249. return AssignString(NULL, (aByteLength >> 1) + (aByteLength & 1), aExactSize);
  250. #else
  251. return AssignString(NULL, aByteLength, aExactSize);
  252. #endif
  253. }
  254. ResultType AssignStringFromCodePage(LPCSTR aBuf, int aLength = -1, UINT aCodePage = CP_ACP);
  255. ResultType AssignStringToCodePage(LPCWSTR aBuf, int aLength = -1, UINT aCodePage = CP_ACP, DWORD aFlags = WC_NO_BEST_FIT_CHARS, char aDefChar = '?');
  256. inline ResultType AssignStringW(LPCWSTR aBuf, int aLength = -1)
  257. {
  258. #ifdef UNICODE
  259. // Pass aExactSize=true for consistency with AssignStringTo/FromCodePage/UTF8.
  260. return AssignString(aBuf, aLength, true);
  261. #else
  262. return AssignStringToCodePage(aBuf, aLength);
  263. #endif
  264. }
  265. inline ResultType Assign(DWORD aValueToAssign)
  266. {
  267. return AssignBinaryNumber(aValueToAssign, VAR_ATTRIB_CONTENTS_OUT_OF_DATE|VAR_ATTRIB_IS_INT64);
  268. }
  269. inline ResultType Assign(int aValueToAssign)
  270. {
  271. return AssignBinaryNumber(aValueToAssign, VAR_ATTRIB_CONTENTS_OUT_OF_DATE|VAR_ATTRIB_IS_INT64);
  272. }
  273. inline ResultType Assign(__int64 aValueToAssign)
  274. {
  275. return AssignBinaryNumber(aValueToAssign, VAR_ATTRIB_CONTENTS_OUT_OF_DATE|VAR_ATTRIB_IS_INT64);
  276. }
  277. inline ResultType Assign(VarSizeType aValueToAssign)
  278. {
  279. return AssignBinaryNumber(aValueToAssign, VAR_ATTRIB_CONTENTS_OUT_OF_DATE|VAR_ATTRIB_IS_INT64);
  280. }
  281. inline ResultType Assign(double aValueToAssign)
  282. {
  283. // The type-casting below interprets the contents of aValueToAssign as an __int64 without actually
  284. // converting from double to __int64. Although the generated code isn't measurably smaller, hopefully
  285. // the compiler resolves it into something that performs better than a memcpy into a temporary variable.
  286. // Benchmarks show that the performance is at most a few percent worse than having code similar to
  287. // AssignBinaryNumber() in here.
  288. return AssignBinaryNumber(*(__int64 *)&aValueToAssign, VAR_ATTRIB_CONTENTS_OUT_OF_DATE|VAR_ATTRIB_IS_DOUBLE);
  289. }
  290. ResultType AssignSkipAddRef(IObject *aValueToAssign);
  291. ResultType Assign(IObject *aValueToAssign)
  292. {
  293. aValueToAssign->AddRef(); // Must be done before Release() in case the only other reference to this object is already in var. Such a case seems too rare to be worth optimizing by returning early.
  294. return AssignSkipAddRef(aValueToAssign);
  295. }
  296. IObject *Object()
  297. {
  298. Var &var = *ResolveAlias();
  299. return var.mObject;
  300. }
  301. IObject *ToObject()
  302. {
  303. Var &var = *ResolveAlias();
  304. return var.IsObject() ? var.mObject : nullptr;
  305. }
  306. void ReleaseObject()
  307. // Caller has ensured that IsObject() == true, not just HasObject().
  308. {
  309. ASSERT(IsObject());
  310. // Remove the attributes applied by AssignSkipAddRef().
  311. mAttrib &= ~(VAR_ATTRIB_IS_OBJECT | VAR_ATTRIB_NOT_NUMERIC);
  312. // Mark the variable as uninitialized so that any attempt to access it from __Delete
  313. // causes an error (but our caller can assign a new value and remove the attribute).
  314. mAttrib |= VAR_ATTRIB_UNINITIALIZED;
  315. // MUST BE DONE AFTER THE ABOVE IN CASE IT TRIGGERS __Delete:
  316. // Release this variable's object. Setting mObject = NULL is not necessary
  317. // since the value of mObject, mContentsInt64 and mContentsDouble is never used
  318. // unless an attribute is present which indicates which one is valid.
  319. mObject->Release();
  320. }
  321. SymbolType IsNumeric()
  322. {
  323. Var &var = *ResolveAlias();
  324. switch (var.mAttrib & VAR_ATTRIB_CACHE) // This switch() method should squeeze a little more performance out of it compared to doing "&" for every attribute. Only works for attributes that are mutually-exclusive, which these are.
  325. {
  326. case VAR_ATTRIB_IS_INT64: return PURE_INTEGER;
  327. case VAR_ATTRIB_IS_DOUBLE: return PURE_FLOAT;
  328. case VAR_ATTRIB_NOT_NUMERIC: return PURE_NOT_NUMERIC;
  329. }
  330. // Since above didn't return, its numeric status isn't yet known, so determine it. For simplicity
  331. // (and because Length() doesn't support VAR_VIRTUAL), the following doesn't check MAX_NUMBER_LENGTH.
  332. // So any string of digits that is too long to be a legitimate number is still treated as a number
  333. // anyway (overflow). Most of our callers are expressions anyway, in which case any unquoted
  334. // series of digits would've been assigned as a pure number and handled above.
  335. // Below passes FALSE for aUpdateContents because we've already confirmed this var doesn't contain
  336. // a cached number (so can't need updating) and to suppress an "uninitialized variable" warning.
  337. // The majority of our callers will call ToInt64/Double() or Contents() after we return, which would
  338. // trigger a second warning if we didn't suppress ours and StdOut/OutputDebug warn mode is in effect.
  339. // IF-IS is the only caller that wouldn't cause a warning, but in that case ExpandArgs() would have
  340. // already caused one.
  341. SymbolType is_pure_numeric = ::IsNumeric(var.Contents(), true, false, true); // Contents() vs. mContents to support VAR_VIRTUAL lvalue in a pure expression such as "a_clipboard:=1,a_clipboard+=5"
  342. if (is_pure_numeric == PURE_NOT_NUMERIC && !VarTypeIsVirtual(var.mType))
  343. var.mAttrib |= VAR_ATTRIB_NOT_NUMERIC;
  344. return is_pure_numeric;
  345. }
  346. SymbolType IsPureNumeric()
  347. // Unlike IsNumeric(), this is purely based on whether a pure number was assigned to this variable.
  348. // Implicitly supports all types of variables, since these attributes are used only by VAR_NORMAL.
  349. {
  350. Var &var = *ResolveAlias();
  351. switch (var.mAttrib & VAR_ATTRIB_CACHE)
  352. {
  353. case VAR_ATTRIB_IS_INT64: return PURE_INTEGER;
  354. case VAR_ATTRIB_IS_DOUBLE: return PURE_FLOAT;
  355. }
  356. return PURE_NOT_NUMERIC;
  357. }
  358. int IsPureNumericOrObject()
  359. {
  360. Var &var = *ResolveAlias();
  361. return var.mAttrib & (VAR_ATTRIB_IS_INT64 | VAR_ATTRIB_IS_DOUBLE | VAR_ATTRIB_IS_OBJECT);
  362. }
  363. __int64 ToInt64()
  364. {
  365. Var &var = *ResolveAlias();
  366. if (var.mAttrib & VAR_ATTRIB_IS_INT64)
  367. return var.mContentsInt64;
  368. if (var.mAttrib & VAR_ATTRIB_IS_DOUBLE)
  369. // Since mContentsDouble is the true value of this var, cast it to __int64 rather than
  370. // calling ATOI64(Contents()), which might produce a different result in some cases.
  371. return (__int64)var.mContentsDouble;
  372. // Otherwise, this var does not contain a pure number.
  373. return ATOI64(var.Contents()); // Call Contents() vs. using mContents in case of VAR_VIRTUAL or VAR_ATTRIB_IS_DOUBLE, and also for maintainability.
  374. }
  375. double ToDouble()
  376. {
  377. Var &var = *ResolveAlias();
  378. if (var.mAttrib & VAR_ATTRIB_IS_DOUBLE)
  379. return var.mContentsDouble;
  380. if (var.mAttrib & VAR_ATTRIB_IS_INT64)
  381. return (double)var.mContentsInt64; // As expected, testing shows that casting an int64 to a double is at least 100 times faster than calling ATOF() on the text version of that integer.
  382. // Otherwise, this var does not contain a pure number.
  383. return ATOF(var.Contents()); // Call Contents() vs. using mContents in case of VAR_VIRTUAL, and also for maintainability and consistency with ToInt64().
  384. }
  385. ResultType ToDoubleOrInt64(ExprTokenType &aToken)
  386. // aToken.var is the same as the "this" var. Converts var into a number and stores it numerically in aToken.
  387. {
  388. Var &var = *ResolveAlias();
  389. switch (aToken.symbol = var.IsNumeric())
  390. {
  391. case PURE_INTEGER:
  392. aToken.value_int64 = var.ToInt64();
  393. break;
  394. case PURE_FLOAT:
  395. aToken.value_double = var.ToDouble();
  396. break;
  397. default: // Not a pure number.
  398. return FAIL;
  399. }
  400. return OK; // Since above didn't return, indicate success.
  401. }
  402. void ToTokenSkipAddRef(ExprTokenType &aToken)
  403. // See ToDoubleOrInt64 for comments.
  404. {
  405. Var &var = *ResolveAlias();
  406. switch (var.mAttrib & VAR_ATTRIB_TYPES)
  407. {
  408. case VAR_ATTRIB_IS_INT64:
  409. aToken.SetValue(var.mContentsInt64);
  410. return;
  411. case VAR_ATTRIB_IS_DOUBLE:
  412. aToken.SetValue(var.mContentsDouble);
  413. return;
  414. case VAR_ATTRIB_IS_OBJECT:
  415. aToken.SetValue(var.mObject);
  416. return;
  417. default:
  418. if (var.mAttrib & VAR_ATTRIB_UNINITIALIZED)
  419. // This is relied upon by callers of CallEnumerator to permit an unset output arg
  420. // to indicate a missing array item. It should not be translated to a parameter's
  421. // default value, because an unset var in that context would have raised an error.
  422. // Some other callers may use this in place of IsUninitialized().
  423. aToken.symbol = SYM_MISSING;
  424. else
  425. aToken.SetValue(var.Contents(), var.Length());
  426. }
  427. }
  428. void ToToken(ExprTokenType &aToken)
  429. {
  430. ToTokenSkipAddRef(aToken);
  431. if (aToken.symbol == SYM_OBJECT)
  432. aToken.object->AddRef();
  433. }
  434. // Not an enum so that it can be global more easily:
  435. #define VAR_NEVER_FREE 0
  436. #define VAR_ALWAYS_FREE 1
  437. #define VAR_FREE_IF_LARGE 2
  438. #define VAR_CLEAR_ALIASES 4
  439. #define VAR_REQUIRE_INIT 8
  440. void Free(int aWhenToFree = VAR_ALWAYS_FREE);
  441. ResultType Append(LPTSTR aStr, VarSizeType aLength);
  442. ResultType AppendIfRoom(LPTSTR aStr, VarSizeType aLength);
  443. void AcceptNewMem(LPTSTR aNewMem, VarSizeType aLength);
  444. void SetLengthFromContents();
  445. static ResultType BackupFunctionVars(UserFunc &aFunc, VarBkp *&aVarBackup, int &aVarBackupCount);
  446. void Backup(VarBkp &aVarBkp);
  447. void Restore(VarBkp &aVarBkp);
  448. static void FreeAndRestoreFunctionVars(UserFunc &aFunc, VarBkp *&aVarBackup, int &aVarBackupCount);
  449. #define DISPLAY_NO_ERROR 0 // Must be zero.
  450. #define DISPLAY_VAR_ERROR 1
  451. #define DISPLAY_FUNC_ERROR 2
  452. #define DISPLAY_CLASS_ERROR 3
  453. #define DISPLAY_GROUP_ERROR 4
  454. #define DISPLAY_METHOD_ERROR 5
  455. #define VALIDATENAME_SUBJECT_INDEX(n) (n-1)
  456. #define VALIDATENAME_SUBJECTS { _T("variable"), _T("function"), _T("class"), _T("group"), _T("method") }
  457. static ResultType ValidateName(LPCTSTR aName, int aDisplayError = DISPLAY_VAR_ERROR);
  458. LPTSTR ObjectToText(LPTSTR aName, LPTSTR aBuf, int aBufSize);
  459. LPTSTR ToText(LPTSTR aBuf, int aBufSize, bool aAppendNewline)
  460. // Caller must ensure that Type() == VAR_NORMAL.
  461. // aBufSize is an int so that any negative values passed in from caller are not lost.
  462. // Caller has ensured that aBuf isn't NULL.
  463. // Translates this var into its text equivalent, putting the result into aBuf and
  464. // returning the position in aBuf of its new string terminator.
  465. {
  466. Var &var = *ResolveAlias();
  467. // v1.0.44.14: Changed it so that ByRef/Aliases report their own name rather than the target's/caller's
  468. // (it seems more useful and intuitive).
  469. var.Contents(); // Update mContents and mLength for use below.
  470. LPTSTR aBuf_orig = aBuf;
  471. switch (var.IsPureNumericOrObject())
  472. {
  473. case VAR_ATTRIB_IS_INT64:
  474. case VAR_ATTRIB_IS_DOUBLE:
  475. // Dont display [len of cap] since it's not relevant for pure numbers.
  476. // This also makes it obvious that the var contains a pure number:
  477. aBuf += sntprintf(aBuf, aBufSize, _T("%s: %s"), mName, var.mCharContents);
  478. break;
  479. case VAR_ATTRIB_IS_OBJECT:
  480. if (var.mType == VAR_VIRTUAL_OBJ)
  481. {
  482. aBuf += sntprintf(aBuf, aBufSize, _T("%s[%s]: %s"), mName, mObject->Type(), var.mCharContents);
  483. break;
  484. }
  485. aBuf = var.ObjectToText(this->mName, aBuf, aBufSize);
  486. break;
  487. default:
  488. if (var.IsUninitialized())
  489. {
  490. aBuf += sntprintf(aBuf, aBufSize, _T("%s: unset"), mName);
  491. break;
  492. }
  493. aBuf += sntprintf(aBuf, BUF_SPACE_REMAINING, _T("%s[%Iu of %Iu]: %-1.60s%s"), mName // mName not var.mName (see comment above).
  494. , var._CharLength(), var._CharCapacity() ? (var._CharCapacity() - 1) : 0 // Use -1 since it makes more sense to exclude the terminator.
  495. , var.mCharContents, var._CharLength() > 60 ? _T("...") : _T(""));
  496. }
  497. if (aAppendNewline && BUF_SPACE_REMAINING >= 2)
  498. {
  499. *aBuf++ = '\r';
  500. *aBuf++ = '\n';
  501. *aBuf = '\0';
  502. }
  503. return aBuf;
  504. }
  505. VarTypeType Type()
  506. {
  507. Var &var = *ResolveAlias();
  508. return var.mType;
  509. }
  510. bool IsVirtual()
  511. {
  512. return VarTypeIsVirtual(Type());
  513. }
  514. bool IsAlias()
  515. {
  516. return mType == VAR_ALIAS;
  517. }
  518. bool IsDirectConstant() // Is a constant and not an alias (i.e. downvar/upvar) for a constant.
  519. {
  520. return mType == VAR_CONSTANT;
  521. }
  522. // Convert VAR_NORMAL to VAR_CONSTANT.
  523. void MakeReadOnly()
  524. {
  525. ASSERT(mType == VAR_NORMAL || mType == VAR_CONSTANT); // Should never be called on VAR_ALIAS or VAR_VIRTUAL.
  526. ASSERT(!(mAttrib & VAR_ATTRIB_UNINITIALIZED));
  527. mType = VAR_CONSTANT;
  528. }
  529. #define VAR_IS_READONLY(var) ((var).IsReadOnly()) // This used to rely on var.Type(), which is no longer enough.
  530. bool IsReadOnly()
  531. {
  532. auto &var = *ResolveAlias();
  533. return var.mType == VAR_CONSTANT || (var.mType == VAR_VIRTUAL && !var.HasSetter());
  534. }
  535. bool IsStatic()
  536. {
  537. return (mScope & VAR_LOCAL_STATIC);
  538. }
  539. bool IsLocal()
  540. {
  541. // Since callers want to know whether this variable is local, even if it's a local alias for a
  542. // global, don't use the method below:
  543. // return (mType == VAR_ALIAS) ? mAliasFor->mIsLocal : mIsLocal;
  544. return (mScope & VAR_LOCAL);
  545. }
  546. bool IsNonStaticLocal()
  547. {
  548. // Since callers want to know whether this variable is local, even if it's a local alias for a
  549. // global, don't resolve VAR_ALIAS.
  550. // Even a ByRef local is considered local here because callers are interested in whether this
  551. // variable can vary from call to call to the same function (and a ByRef can vary in what it
  552. // points to). Variables that vary can thus be altered by the backup/restore process.
  553. return (mScope & (VAR_LOCAL|VAR_LOCAL_STATIC)) == VAR_LOCAL;
  554. }
  555. bool IsFuncParam()
  556. {
  557. return (mScope & VAR_LOCAL_FUNCPARAM);
  558. }
  559. bool IsDeclared()
  560. // Returns true if this is a declared var, such as "local var", "static var" or a func param.
  561. {
  562. return (mScope & VAR_DECLARED);
  563. }
  564. bool IsExported()
  565. {
  566. return (mScope & VAR_EXPORTED);
  567. }
  568. UCHAR &Scope()
  569. {
  570. return mScope;
  571. }
  572. static LPCTSTR DeclarationType(int aDeclType)
  573. {
  574. if (aDeclType & VAR_LOCAL)
  575. {
  576. if (aDeclType & VAR_LOCAL_STATIC)
  577. return _T("static");
  578. if (aDeclType & VAR_LOCAL_FUNCPARAM)
  579. return _T("parameter");
  580. return _T("local");
  581. }
  582. return _T("global");
  583. }
  584. bool IsAssignedSomewhere()
  585. {
  586. //return mAttrib & VAR_ATTRIB_HAS_ASSIGNMENT;
  587. return (mAttrib & ~VAR_ATTRIB_ALREADY_WARNED) != VAR_ATTRIB_UNINITIALIZED;
  588. // When this function is called (at load time), any of the other attributes
  589. // would mean that this var has a value, which means that it doesn't require
  590. // an assignment. If it lacks all attributes, it's presumably a built-in var.
  591. }
  592. void MarkAssignedSomewhere()
  593. {
  594. mAttrib |= VAR_ATTRIB_HAS_ASSIGNMENT;
  595. if (mType == VAR_ALIAS)
  596. mAliasFor->MarkAssignedSomewhere();
  597. }
  598. bool HasAlreadyWarned()
  599. {
  600. return mAttrib & VAR_ATTRIB_ALREADY_WARNED;
  601. }
  602. void MarkAlreadyWarned()
  603. {
  604. mAttrib |= VAR_ATTRIB_ALREADY_WARNED;
  605. }
  606. bool IsObject() // L31: Indicates this var contains an object reference which must be released if the var is emptied.
  607. {
  608. return (mAttrib & VAR_ATTRIB_IS_OBJECT);
  609. }
  610. bool HasObject() // L31: Indicates this var's effective value is an object reference.
  611. {
  612. Var &var = *ResolveAlias();
  613. return var.IsObject();
  614. }
  615. VarSizeType ByteCapacity()
  616. // Capacity includes the zero terminator (though if capacity is zero, there will also be a zero terminator in mContents due to it being "").
  617. {
  618. Var &var = *ResolveAlias();
  619. return var.mByteCapacity;
  620. }
  621. VarSizeType CharCapacity()
  622. {
  623. return ByteCapacity() / sizeof(TCHAR);
  624. }
  625. UNICODE_CHECK VarSizeType Capacity()
  626. {
  627. return CharCapacity();
  628. }
  629. BOOL HasContents()
  630. // A fast alternative to Length() that avoids updating mContents.
  631. // Caller must ensure that Type() is VAR_NORMAL.
  632. {
  633. Var &var = *ResolveAlias();
  634. // mAttrib is checked because mByteLength isn't applicable when the var contains
  635. // a pure number or an object.
  636. return (var.mAttrib & VAR_ATTRIB_TYPES) ? TRUE : var.mByteLength != 0;
  637. }
  638. VarSizeType &ByteLength()
  639. // This should not be called to discover a non-NORMAL var's length (nor that of an environment variable)
  640. // because their lengths aren't knowable without calling Get().
  641. // Returns a reference so that caller can use this function as an lvalue.
  642. {
  643. Var &var = *ResolveAlias();
  644. // There's no apparent reason to avoid using mByteLength for VAR_VIRTUAL,
  645. // so it's used temporarily despite the comments below. Even if mByteLength
  646. // isn't always accurate, it's no less accurate than a static variable would be.
  647. //if (mType == VAR_NORMAL)
  648. {
  649. if (var.mAttrib & VAR_ATTRIB_CONTENTS_OUT_OF_DATE)
  650. var.UpdateContents(); // Update mContents (and indirectly, mByteLength).
  651. return var.mByteLength;
  652. }
  653. // Since the length of the clipboard isn't normally tracked, we just return a
  654. // temporary storage area for the caller to use. Note: This approach is probably
  655. // not thread-safe, but currently there's only one thread so it's not an issue.
  656. // For reserved vars do the same thing as above, but this function should never
  657. // be called for them:
  658. //static VarSizeType length; // Must be static so that caller can use its contents. See above.
  659. //return length;
  660. }
  661. VarSizeType SetCharLength(VarSizeType len)
  662. {
  663. ByteLength() = len * sizeof(TCHAR);
  664. return len;
  665. }
  666. VarSizeType CharLength()
  667. {
  668. return ByteLength() / sizeof(TCHAR);
  669. }
  670. UNICODE_CHECK VarSizeType Length()
  671. {
  672. return CharLength();
  673. }
  674. //BYTE *ByteContents(BOOL aAllowUpdate = TRUE)
  675. //{
  676. // return (BYTE *) CharContents(aAllowUpdate);
  677. //}
  678. TCHAR *Contents(BOOL aAllowUpdate = TRUE)
  679. // Callers should almost always pass TRUE for aAllowUpdate because any caller who wants to READ from
  680. // mContents would almost always want it up-to-date. Any caller who wants to WRITE to mContents would
  681. // would almost always have called Assign(NULL, ...) prior to calling Contents(), which would have
  682. // cleared the VAR_ATTRIB_CONTENTS_OUT_OF_DATE flag.
  683. // UPDATE: If the variable is known to already be "up to date", passing FALSE reduces code size,
  684. // as the compiler often inlines the function and is able to optimize out the aAllowUpdate branches
  685. // (although the final result can be larger if it allows the compiler to inline more functions).
  686. {
  687. if (mType == VAR_ALIAS)
  688. return mAliasFor->Contents(aAllowUpdate);
  689. if ((mAttrib & VAR_ATTRIB_CONTENTS_OUT_OF_DATE) && aAllowUpdate) // VAR_ATTRIB_CONTENTS_OUT_OF_DATE is checked here and in the function below, for performance.
  690. UpdateContents(); // This also clears the VAR_ATTRIB_CONTENTS_OUT_OF_DATE.
  691. if (VarTypeIsVirtual(mType) && !(mAttrib & VAR_ATTRIB_VIRTUAL_OPEN) && aAllowUpdate)
  692. {
  693. // This var isn't open for writing, so populate mCharContents with its current value.
  694. PopulateVirtualVar();
  695. // The following ensures the contents are updated each time Contents() is called:
  696. mAttrib &= ~VAR_ATTRIB_VIRTUAL_OPEN;
  697. }
  698. return mCharContents;
  699. }
  700. // Populate a virtual var with its current value, as a string.
  701. // Caller has verified this->IsVirtual().
  702. ResultType PopulateVirtualVar();
  703. void ConvertToNonAliasIfNecessary() // __forceinline because it's currently only called from one place.
  704. // When this function actually converts an alias into a normal variable, the variable's old
  705. // attributes (especially mContents and mCapacity) become dominant again. This prevents a memory
  706. // leak in a case where a UDF is defined to provide a default value for a ByRef parameter, and is
  707. // called both with and without that parameter.
  708. {
  709. mAliasFor = NULL; // This also sets its counterpart in the union (mLength) to zero, which is appropriate because mContents should have been set to blank by a previous call to Free().
  710. mType = VAR_NORMAL; // It might already be this type, so this is just in case it's VAR_ALIAS.
  711. }
  712. Var *GetAliasFor()
  713. {
  714. ASSERT(mType == VAR_ALIAS);
  715. return mAliasFor;
  716. }
  717. Var *ResolveAlias()
  718. {
  719. // Return target if it's an alias, or itself if not.
  720. return mType == VAR_ALIAS ? mAliasFor->ResolveAlias() : this;
  721. }
  722. // Makes this var an alias of aTargetVar, or aTargetVar's target if it's an alias.
  723. // Copies any internal mObject ref used for managing the lifetime of the alias.
  724. void UpdateAlias(Var *aTargetVar);
  725. void UpdateAlias(VarRef *aTargetVar);
  726. void UpdateVirtualObj(IObject *aTargetRef);
  727. // Unconditionally makes this var an alias of aTargetVar, without resolving aliases.
  728. // Caller must ensure aTargetVar != nullptr && aTargetVar != this.
  729. void SetAliasDirect(Var *aTargetVar)
  730. {
  731. mAliasFor = aTargetVar; // Should always be non-NULL due to various checks elsewhere.
  732. mType = VAR_ALIAS; // It might already be this type, so this is just in case it's VAR_NORMAL.
  733. }
  734. // Retrieves the IObject interface for managing this var's lifetime,
  735. // converting this var to an alias for a new freevar if needed.
  736. IObject *GetRef();
  737. ResultType MoveToNewFreeVar(Var &aOther);
  738. ResultType Close()
  739. {
  740. if (mType == VAR_ALIAS)
  741. return mAliasFor->Close();
  742. if (VarTypeIsVirtual(mType))
  743. {
  744. // Commit the value in our temporary buffer.
  745. auto result = AssignVirtual(ExprTokenType(mCharContents, CharLength()));
  746. Free(); // Free temporary memory and remove VAR_ATTRIB_VIRTUAL_OPEN.
  747. return result;
  748. }
  749. // VAR_ATTRIB_CONTENTS_OUT_OF_DATE is removed below for maintainability; it shouldn't be
  750. // necessary because any caller of Close() should have previously called something that
  751. // updates the flags, such as Contents().
  752. mAttrib &= ~VAR_ATTRIB_OFTEN_REMOVED;
  753. return OK; // In all other cases.
  754. }
  755. // Constructor:
  756. Var(LPTSTR aVarName, UCHAR aScope)
  757. // The caller must ensure that aVarName is non-null.
  758. : mScope(aScope)
  759. , mAttrib(VAR_ATTRIB_UNINITIALIZED) // Seems best not to init empty vars to VAR_ATTRIB_NOT_NUMERIC because it would reduce maintainability, plus finding out whether an empty var is numeric via IsNumeric() is a very fast operation.
  760. , mName(aVarName) // Caller gave us a pointer to dynamic memory for this.
  761. , mType(VAR_NORMAL)
  762. {
  763. }
  764. Var(LPTSTR aVarName, VarEntry *aBuiltIn, UCHAR aScope)
  765. // The caller must ensure that aVarName is non-null.
  766. : mScope(aScope)
  767. , mName(aVarName) // Caller gave us a pointer to dynamic memory for this.
  768. , mAttrib(0) // Any vars that aren't VAR_NORMAL are considered initialized, by definition.
  769. , mType(VAR_VIRTUAL)
  770. , mVV(&aBuiltIn->type)
  771. {
  772. }
  773. Var() : Var(_T(""), VAR_VARREF)
  774. {
  775. // Vars constructed this way are for temporary use, and therefore must have mHowAllocated set
  776. // as below to prevent the use of SimpleHeap::Malloc(). Otherwise, each Var could allocate
  777. // some memory which cannot be freed until the program exits.
  778. mHowAllocated = ALLOC_MALLOC;
  779. }
  780. Var(IObject *aRef)
  781. // The caller must ensure that aVarName is non-null.
  782. : mType(VAR_VIRTUAL_OBJ), mObject(aRef)
  783. , mScope(0), mName(_T("")), mAttrib(VAR_ATTRIB_IS_OBJECT)
  784. , mHowAllocated(ALLOC_DISABLED)
  785. {
  786. ASSERT(aRef);
  787. }
  788. void *operator new(size_t aBytes) {return SimpleHeap::Malloc(aBytes);}
  789. void *operator new(size_t aBytes, void *p) {return p;}
  790. void *operator new[](size_t aBytes) {return SimpleHeap::Malloc(aBytes);}
  791. void operator delete(void *aPtr) {}
  792. void operator delete(void *aPtr, void *) {}
  793. void operator delete[](void *aPtr) {}
  794. ResultType InitializeConstant();
  795. bool IsUninitializedNormalVar()
  796. {
  797. Var &var = *ResolveAlias();
  798. return var.mType == VAR_NORMAL && (var.mAttrib & VAR_ATTRIB_UNINITIALIZED);
  799. }
  800. bool IsUninitialized()
  801. {
  802. Var &var = *ResolveAlias();
  803. return var.mAttrib & VAR_ATTRIB_UNINITIALIZED;
  804. }
  805. void MarkInitialized()
  806. {
  807. Var &var = *ResolveAlias();
  808. var.mAttrib &= ~VAR_ATTRIB_UNINITIALIZED;
  809. }
  810. void MarkUninitialized()
  811. {
  812. Var& var = *ResolveAlias();
  813. var.mAttrib |= VAR_ATTRIB_UNINITIALIZED;
  814. }
  815. ResultType Uninitialize(int aWhenToFree = VAR_FREE_IF_LARGE)
  816. {
  817. if (IsVirtual())
  818. {
  819. ExprTokenType unset;
  820. unset.symbol = SYM_MISSING;
  821. return AssignVirtual(unset);
  822. }
  823. Free(aWhenToFree | VAR_REQUIRE_INIT);
  824. return OK;
  825. }
  826. }; // class Var
  827. #pragma pack(pop) // Calling pack with no arguments restores the default value (which is 8, but "the alignment of a member will be on a boundary that is either a multiple of n or a multiple of the size of the member, whichever is smaller.")
  828. #pragma warning(pop)
  829. class VarRef : public ObjectBase, public Var
  830. {
  831. public:
  832. VarRef() {}
  833. ~VarRef()
  834. {
  835. Free(VAR_ALWAYS_FREE | VAR_CLEAR_ALIASES | VAR_REQUIRE_INIT);
  836. }
  837. IObject_Type_Impl("VarRef");
  838. ::Object *Base() { return ::Object::sVarRefPrototype; }
  839. void *operator new(size_t aBytes) { return malloc(aBytes); } // Must override Var::new, which uses SimpleHeap::Malloc.
  840. void *operator new[](size_t aBytes) { return malloc(aBytes); }
  841. void operator delete(void *aPtr) { free(aPtr); }
  842. void operator delete[](void *aPtr) { free(aPtr); }
  843. void __Value(ResultToken &aResultToken, int aID, int aFlags, ExprTokenType *aParam[], int aParamCount);
  844. static ObjectMember sMembers[];
  845. };
  846. #endif