"Fossies" - the Fresh Open Source Software Archive

Member "AutoHotkey_L-1.1.33.09/source/var.cpp" (8 May 2021, 78162 Bytes) of package /windows/misc/AutoHotkey_L-1.1.33.09.zip:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style: standard) with prefixed line numbers and code folding option. Alternatively you can here view or download the uninterpreted source code file. For more information about "var.cpp" see the Fossies "Dox" file reference documentation.

    1 /*
    2 AutoHotkey
    3 
    4 Copyright 2003-2009 Chris Mallett (support@autohotkey.com)
    5 
    6 This program is free software; you can redistribute it and/or
    7 modify it under the terms of the GNU General Public License
    8 as published by the Free Software Foundation; either version 2
    9 of the License, or (at your option) any later version.
   10 
   11 This program is distributed in the hope that it will be useful,
   12 but WITHOUT ANY WARRANTY; without even the implied warranty of
   13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   14 GNU General Public License for more details.
   15 */
   16 
   17 #include "stdafx.h" // pre-compiled headers
   18 #include "var.h"
   19 #include "globaldata.h" // for g_script
   20 
   21 
   22 // Init static vars:
   23 TCHAR Var::sEmptyString[] = _T(""); // For explanation, see its declaration in .h file.
   24 
   25 
   26 ResultType Var::AssignHWND(HWND aWnd)
   27 {
   28     // For backward compatibility, tradition, and the fact that operations involving HWNDs tend not to
   29     // be nearly as performance-critical as pure-math expressions, HWNDs are stored as a hex string,
   30     // and thus UpdateBinaryInt64() isn't called here.
   31     // Older comment: Always assign as hex for better compatibility with Spy++ and other apps that
   32     // report window handles.
   33     TCHAR buf[MAX_INTEGER_SIZE];
   34     return Assign(HwndToString(aWnd, buf));
   35 }
   36 
   37 
   38 
   39 ResultType Var::Assign(Var &aVar)
   40 // Assign some other variable to the "this" variable.
   41 // Although this->Type() can be VAR_CLIPBOARD, caller must ensure that aVar.Type()==VAR_NORMAL.
   42 // Returns OK or FAIL.
   43 {
   44     // Below relies on the fact that aliases can't point to other aliases (enforced by UpdateAlias()).
   45     Var &source_var = aVar.mType == VAR_ALIAS ? *aVar.mAliasFor : aVar;
   46     Var &target_var = *(mType == VAR_ALIAS ? mAliasFor : this);
   47 
   48     if (source_var.mAttrib & VAR_ATTRIB_HAS_VALID_INT64) // A binary Int64 is cached.
   49     {
   50         if (!(source_var.mAttrib & VAR_ATTRIB_CONTENTS_OUT_OF_DATE)) // Since contents are in sync with the cached binary integer, must also copy the text contents to preserve any leading/trailing whitespace in it.
   51         {
   52             // Since source_var's contents are in sync with its cached binary number, in addition to copying
   53             // source_var's binary number, must also copy its text contents if it has any leading/trailing
   54             // whitespace or unusual formatting that the script may rely on to be copied.  For example:
   55             //    Var := " 055. "  ; Leading+trailing whitespace, leading zero, and trailing decimal point.
   56             //    if (Var == 55)     ; This statement causes Var to acquire a cached binary number, yet it's in sync with contents because it represents contents (but not necessarily vice versa).
   57             //    ...
   58             // It seems worth peeking into beginning and end of var to check for such special formatting
   59             // because it potentially avoids the copying of mContents, which in turn potentially avoids
   60             // allocating or expanding memory for target_var.mContents.
   61             int c1 = *source_var.mCharContents; // For performance, resolve once and store as int vs. char.
   62             int c2 = source_var.mCharContents[source_var._CharLength()-1]; // No need to check mLength>0 because at this point there's a cached binary number AND mContents is in sync with it, so mContents is non-empty by definition.
   63             if (   IS_SPACE_OR_TAB(c1) // IS_SPACE_OR_TAB() is the rule used by IsPureNumeric() to permit
   64                 || IS_SPACE_OR_TAB(c2) // leading/trailing whitespace, so it's the right rule to determine whether mContents is technically numeric yet in an unusual format.
   65                 || c1 == '0' || c1 == '+'   ) // Retain leading '0' and '+' (even hex like "0x5" because script might rely on exact formatting of such numbers to be retained in mContents).
   66                 // No need to check for leading/trailing '.' or scientific notation because those would
   67                 // never have caused an integer to be cached (float instead), so they wouldn't occur in this
   68                 // section.  Also, integers that are too long (and thus perhaps intended to be a series
   69                 // of digits rather than an integer) are not checked because they're partially checked
   70                 // at loadtime, and if encountered here at runtime, the mere fact that a cached integer
   71                 // exists for that string implies the script has done something to cache it, such as
   72                 // "if (var > 15)", which implies the script is currently using that variable as a number.
   73                 // So it seems too rare to justify extra checking such as mLength > MAX_INTEGER_LENGTH.
   74             {
   75                 if (!target_var.Assign(source_var.mCharContents, source_var._CharLength())) // Pass length to improve performance. It isn't necessary to call Contents()/Length() because they must be already up-to-date due to earlier checks.
   76                     return FAIL;
   77                 // Below must be done AFTER the above because above's Assign() invalidates the cache, but the
   78                 // cache should be left valid.
   79                 target_var.UpdateBinaryInt64(source_var.mContentsInt64); // Except when passing VAR_ATTRIB_CONTENTS_OUT_OF_DATE, all callers of UpdateBinaryInt64() must ensure that mContents is a pure number (e.g. NOT 123abc).
   80                 return OK;
   81             }
   82             //else it doesn't have any leading/trailing space or unusual formatting to preserve, so can
   83             // write to the cache, which allows mContents to be updated later on demand.
   84         }
   85         //else number cache is out-of-sync with mContents, so there is no need to copy over mContents because
   86         // it will get overwritten by the cached number the next time anyone calls Contents().
   87 
   88         // Since above didn't return, copy the cached number only, not mContents.  But must also mark
   89         // the mContents as out-of-date because it will be kept blank until something actually needs it.
   90         target_var.UpdateBinaryInt64(source_var.mContentsInt64, VAR_ATTRIB_HAS_VALID_INT64|VAR_ATTRIB_CONTENTS_OUT_OF_DATE);
   91         return OK;
   92     }
   93 
   94     if (source_var.mAttrib & VAR_ATTRIB_HAS_VALID_DOUBLE) // A binary double is cached.
   95     {
   96         if (!(source_var.mAttrib & VAR_ATTRIB_CONTENTS_OUT_OF_DATE)) // See comments in similar section above.
   97         {
   98             // Analyzing the mContents of floating point variables (like was done for cached integers above)
   99             // doesn't seem worth it because benchmarks show that in percentage terms, caching floats doesn't
  100             // offer nearly as much performance improvement as caching integers. In addition, the analysis
  101             // would be much more complicated -- so much so that it might entirely negate any performance
  102             // benefits, not to mention the extra code size/complexity.  Here is an example of one of the
  103             // issues:
  104             //    Var := 1.12345678  ; Assign higher precision than the default SetFormat.
  105             //    if (Var > 5)  ; This creates a cached binary double in Var.
  106             //       Sleep -1
  107             //    Var2 := Var  ; If this were to copy only the cached double (and not mContents too), the next time someone asked for Var's text, SetFormat would wrongly be applied to it, resulting in a loss of displayed precision (but not internal precision).
  108             // Other examples that would be affected include 1.0 (low precision), 1.0e1 (scientific notation),
  109             // .5 (leading decimal point), 5. (trailing decimal point), and also the cases that affect
  110             // integers such as "005.5", "+5.5", and leading/trailing whitespace.
  111             if (!target_var.Assign(source_var.mCharContents, source_var._CharLength())) // See comments in similar section above.
  112                 return FAIL;
  113             // Below must be done AFTER the above because above's Assign() invalidates the cache, but the
  114             // cache should be left valid.
  115             target_var.UpdateBinaryDouble(source_var.mContentsDouble); // When not passing VAR_ATTRIB_CONTENTS_OUT_OF_DATE, all callers of UpdateBinaryDouble() must ensure that mContents is a pure number (e.g. NOT 123abc).
  116         }
  117         else
  118             target_var.UpdateBinaryDouble(source_var.mContentsDouble, VAR_ATTRIB_CONTENTS_OUT_OF_DATE); // See comments in similar section above.
  119         return OK;
  120     }
  121 
  122     if (source_var.mAttrib & VAR_ATTRIB_BINARY_CLIP) // Caller has ensured that source_var's Type() is VAR_NORMAL.
  123         return target_var.AssignBinaryClip(source_var); // Caller wants a variable with binary contents assigned (copied) to another variable (usually VAR_CLIPBOARD).
  124 
  125     if (source_var.IsObject()) // L31
  126         return target_var.Assign(source_var.mObject);
  127 
  128     // Otherwise:
  129     source_var.MaybeWarnUninitialized();
  130     return target_var.Assign(source_var.mCharContents, source_var._CharLength()); // Pass length to improve performance. It isn't necessary to call Contents()/Length() because they must be already up-to-date because there is no binary number to update them from (if there were, the above would have returned).  Also, caller ensured Type()==VAR_NORMAL.
  131 }
  132 
  133 
  134 
  135 ResultType Var::Assign(ExprTokenType &aToken)
  136 // Returns OK or FAIL.
  137 // Writes aToken's value into aOutputVar based on the type of the token.
  138 // Caller must ensure that aToken.symbol is an operand (not an operator or other symbol).
  139 // Caller must ensure that if aToken.symbol==SYM_VAR, aToken.var->Type()==VAR_NORMAL, not the clipboard or
  140 // any built-in var.  However, this->Type() can be VAR_CLIPBOARD.
  141 {
  142     switch (aToken.symbol)
  143     {
  144     case SYM_INTEGER: return Assign(aToken.value_int64); // Listed first for performance because it's Likely the most common from our callers.
  145     case SYM_OPERAND: // Listed near the top for performance.
  146         if (aToken.buf) // The "buf" of a SYM_OPERAND is non-NULL if it's a pure integer.
  147         {
  148             if (*aToken.marker != '0') // It's not an unusual format like 00123 (leading zeroes) or 0xFF (hex).
  149                 return Assign(*(__int64 *)aToken.buf);
  150             // Otherwise, it's something like 0xFF or 00123. For backward compatibility, preserve that formatting
  151             // in case the contents of this variable will go on to be displayed or used in a string operation.
  152             // The following "double assign" is similar to that in Var::Assign(Var &aVar):
  153             if (!Assign(aToken.marker))
  154                 return FAIL;
  155             // Below must be done AFTER the above because above's Assign() invalidates the cache, but the
  156             // cache should be left valid.
  157             UpdateBinaryInt64(*(__int64 *)aToken.buf); // Except when passing VAR_ATTRIB_CONTENTS_OUT_OF_DATE, all callers of UpdateBinaryInt64() must ensure that mContents is a pure number (e.g. NOT 123abc).
  158             return OK;
  159         }
  160         //else there is no binary integer; so don't return, continue on to the bottom.
  161         break;
  162     case SYM_VAR:     return Assign(*aToken.var); // Caller has ensured that var->Type()==VAR_NORMAL (it's only VAR_CLIPBOARD for certain expression lvalues, which would never be assigned here because aToken is an rvalue).
  163     case SYM_FLOAT:   return Assign(aToken.value_double); // Listed last because it's probably the least common.
  164     case SYM_OBJECT:  return Assign(aToken.object); // L31
  165     }
  166     // Since above didn't return, it's SYM_STRING, or a SYM_OPERAND that lacks a binary-integer counterpart.
  167     return Assign(aToken.marker);
  168 }
  169 
  170 
  171 
  172 ResultType Var::AssignClipboardAll()
  173 // Caller must ensure that "this" is a normal variable or the clipboard (though if it's the clipboard, this
  174 // function does nothing).
  175 {
  176     if (mType == VAR_CLIPBOARD) // Seems pointless to do Clipboard:=ClipboardAll, and the below isn't equipped
  177         return OK;              // to handle it, so make this have no effect.
  178 
  179     return GetClipboardAll(mType == VAR_ALIAS ? mAliasFor : this, NULL, NULL);
  180 }
  181 
  182 ResultType Var::GetClipboardAll(Var *aOutputVar, void **aData, size_t *aDataSize)
  183 {
  184     if (!g_clip.Open())
  185         return g_script.ScriptError(CANT_OPEN_CLIPBOARD_READ);
  186 
  187     // Calculate the size needed:
  188     // EnumClipboardFormats() retrieves all formats, including synthesized formats that don't
  189     // actually exist on the clipboard but are instead constructed on demand.  Unfortunately,
  190     // there doesn't appear to be any way to reliably determine which formats are real and
  191     // which are synthesized (if there were such a way, a large memory savings could be
  192     // realized by omitting the synthesized formats from the saved version). One thing that
  193     // is certain is that the "real" format(s) come first and the synthesized ones afterward.
  194     // However, that's not quite enough because although it is recommended that apps store
  195     // the primary/preferred format first, the OS does not enforce this.  For example, testing
  196     // shows that the apps do not have to store CF_UNICODETEXT prior to storing CF_TEXT,
  197     // in which case the clipboard might have inaccurate CF_TEXT as the first element and
  198     // more accurate/complete (non-synthesized) CF_UNICODETEXT stored as the next.
  199     // In spite of the above, the below seems likely to be accurate 99% or more of the time,
  200     // which seems worth it given the large savings of memory that are achieved, especially
  201     // for large quantities of text or large images. Confidence is further raised by the
  202     // fact that MSDN says there's no advantage/reason for an app to place multiple formats
  203     // onto the clipboard if those formats are available through synthesis.
  204     // And since CF_TEXT always(?) yields synthetic CF_OEMTEXT and CF_UNICODETEXT, and
  205     // probably (but less certainly) vice versa: if CF_TEXT is listed first, it might certainly
  206     // mean that the other two do not need to be stored.  There is some slight doubt about this
  207     // in a situation where an app explicitly put CF_TEXT onto the clipboard and then followed
  208     // it with CF_UNICODETEXT that isn't synthesized, nor does it match what would have been
  209     // synthesized. However, that seems extremely unlikely (it would be much more likely for
  210     // an app to store CF_UNICODETEXT *first* followed by custom/non-synthesized CF_TEXT, but
  211     // even that might be unheard of in practice).  So for now -- since there is no documentation
  212     // to be found about this anywhere -- it seems best to omit some of the most common
  213     // synthesized formats:
  214     // CF_TEXT is the first of three text formats to appear: Omit CF_OEMTEXT and CF_UNICODETEXT.
  215     //    (but not vice versa since those are less certain to be synthesized)
  216     //    (above avoids using four times the amount of memory that would otherwise be required)
  217     //    UPDATE: Only the first text format is included now, since MSDN says there is no
  218     //    advantage/reason to having multiple non-synthesized text formats on the clipboard.
  219     //    UPDATE: MS Word 2010 (and perhaps other versions) stores CF_TEXT before CF_UNICODETEXT,
  220     //    even when CF_TEXT is incomplete/inaccurate. Since there's no way to know whether it was
  221     //    synthesized, it is now stored unconditionally. CF_TEXT and CF_OEMTEXT are discarded to
  222     //    save memory and because they should always be synthesized correctly.
  223     // CF_DIB: Always omit this if CF_DIBV5 is available (which must be present on Win2k+, at least
  224     // as a synthesized format, whenever CF_DIB is present?) This policy seems likely to avoid
  225     // the issue where CF_DIB occurs first yet CF_DIBV5 that comes later is *not* synthesized,
  226     // perhaps simply because the app stored DIB prior to DIBV5 by mistake (though there is
  227     // nothing mandatory, so maybe it's not really a mistake). Note: CF_DIBV5 supports alpha
  228     // channel / transparency, and perhaps other things, and it is likely that when synthesized,
  229     // no information of the original CF_DIB is lost. Thus, when CF_DIBV5 is placed back onto
  230     // the clipboard, any app that needs CF_DIB will have it synthesized back to the original
  231     // data (hopefully). It's debatable whether to do it that way or store whichever comes first
  232     // under the theory that an app would never store both formats on the clipboard since MSDN
  233     // says: "If the system provides an automatic type conversion for a particular clipboard format,
  234     // there is no advantage to placing the conversion format(s) on the clipboard."
  235     HGLOBAL hglobal;
  236     SIZE_T size;
  237     UINT format;
  238     VarSizeType space_needed;
  239     UINT dib_format_to_omit = 0;
  240     BOOL save_null_data;
  241     // Start space_needed off at 4 to allow room for guaranteed final termination of the variable's contents.
  242     // The termination must be of the same size as format because a single-byte terminator would
  243     // be read in as a format of 0x00?????? where ?????? is an access violation beyond the buffer.
  244     for (space_needed = sizeof(format), format = 0; format = EnumClipboardFormats(format);)
  245     {
  246         switch (format)
  247         {
  248         case CF_BITMAP:
  249         case CF_ENHMETAFILE:
  250         case CF_DSPENHMETAFILE:
  251             // These formats appear to be specific handle types, not always safe to call GlobalSize() for.
  252             continue;
  253         }
  254         // No point in calling GetLastError() since it would never be executed because the loop's
  255         // condition breaks on zero return value.
  256         if (format == CF_TEXT || format == CF_OEMTEXT // This format is excluded in favour of CF_UNICODETEXT.
  257             || format == dib_format_to_omit) // ... or this format was marked excluded by a prior iteration.
  258             continue;
  259         // GetClipboardData() causes Task Manager to report a (sometimes large) increase in
  260         // memory utilization for the script, which is odd since it persists even after the
  261         // clipboard is closed.  However, when something new is put onto the clipboard by the
  262         // the user or any app, that memory seems to get freed automatically.  Also, 
  263         // GetClipboardData(49356) fails in MS Visual C++ when the copied text is greater than
  264         // about 200 KB (but GetLastError() returns ERROR_SUCCESS).  When pasting large sections
  265         // of colorized text into MS Word, it can't get the colorized text either (just the plain
  266         // text). Because of this example, it seems likely it can fail in other places or under
  267         // other circumstances, perhaps by design of the app. Therefore, be tolerant of failures
  268         // because partially saving the clipboard seems much better than aborting the operation.
  269         if (hglobal = g_clip.GetClipboardDataTimeout(format, &save_null_data))
  270         {
  271             space_needed += (VarSizeType)(sizeof(format) + sizeof(size) + GlobalSize(hglobal)); // The total amount of storage space required for this item.
  272             if (!dib_format_to_omit)
  273             {
  274                 if (format == CF_DIB)
  275                     dib_format_to_omit = CF_DIBV5;
  276                 else if (format == CF_DIBV5)
  277                     dib_format_to_omit = CF_DIB;
  278             }
  279             // Currently CF_ENHMETAFILE isn't supported, so no need for this section:
  280             //if (!meta_format_to_omit) // Checked for the same reasons as dib_format_to_omit.
  281             //{
  282             //  if (format == CF_ENHMETAFILE)
  283             //      meta_format_to_omit = CF_METAFILEPICT;
  284             //  else if (format == CF_METAFILEPICT)
  285             //      meta_format_to_omit = CF_ENHMETAFILE;
  286             //}
  287         }
  288         else if (save_null_data)
  289             space_needed += (VarSizeType)(sizeof(format) + sizeof(size));
  290         //else omit this format from consideration.
  291     }
  292 
  293     if (space_needed == sizeof(format)) // This works because even a single empty format requires space beyond sizeof(format) for storing its format+size.
  294     {
  295         g_clip.Close();
  296         if (aOutputVar)
  297             return aOutputVar->Assign(); // Nothing on the clipboard, so just make the variable blank.
  298         *aData = NULL;
  299         *aDataSize = 0;
  300         return OK;
  301     }
  302 
  303     LPVOID binary_contents; 
  304     
  305     // Resize the output variable, if needed:
  306     if (aOutputVar)
  307         if (aOutputVar->SetCapacity(space_needed, true, false))
  308         {
  309             binary_contents = aOutputVar->mCharContents; // mCharContents vs. Contents() is okay since aOutputVar type is never VAR_ALIAS.
  310             space_needed = aOutputVar->mByteCapacity; // Update to actual granted capacity, which might be a little larger than requested.
  311         }
  312         else
  313             binary_contents = NULL; // For detection below.
  314     else
  315         *aData = binary_contents = malloc(space_needed);
  316     
  317     if (!binary_contents)
  318     {
  319         g_clip.Close();
  320         if (aOutputVar)
  321             return FAIL; // Above should have already reported the error.
  322         return g_script.ScriptError(ERR_OUTOFMEM);
  323     }
  324 
  325     // Retrieve and store all the clipboard formats.  Because failures of GetClipboardData() are now
  326     // tolerated, it seems safest to recalculate the actual size (actual_space_needed) of the data
  327     // in case it varies from that found in the estimation phase.  This is especially necessary in
  328     // case GlobalLock() ever fails, since that isn't even attempted during the estimation phase.
  329     // Otherwise, the variable's mLength member would be set to something too high (the estimate),
  330     // which might cause problems elsewhere.
  331     LPVOID hglobal_locked;
  332     VarSizeType added_size, actual_space_used;
  333     for (actual_space_used = sizeof(format), format = 0; format = EnumClipboardFormats(format);)
  334     {
  335         switch (format)
  336         {
  337         case CF_BITMAP:
  338         case CF_ENHMETAFILE:
  339         case CF_DSPENHMETAFILE:
  340             // These formats appear to be specific handle types, not always safe to call GlobalSize() for.
  341             continue;
  342         }
  343         // No point in calling GetLastError() since it would never be executed because the loop's
  344         // condition breaks on zero return value.
  345         if (format == CF_TEXT || format == CF_OEMTEXT
  346             || format == dib_format_to_omit /*|| format == meta_format_to_omit*/)
  347             continue;
  348         // Although the GlobalSize() documentation implies that a valid HGLOBAL should not be zero in
  349         // size, it does happen, at least in MS Word and for CF_BITMAP.  Therefore, in order to save
  350         // the clipboard as accurately as possible, also save formats whose size is zero.  Note that
  351         // GlobalLock() fails to work on hglobals of size zero, so don't do it for them.
  352         hglobal = g_clip.GetClipboardDataTimeout(format, &save_null_data);
  353         if (hglobal)
  354             size = GlobalSize(hglobal);
  355         else if (save_null_data)
  356             size = 0; // This format usually has NULL data.
  357         else
  358             continue; // GetClipboardData() failed: skip this format.
  359         if (!size || (hglobal_locked = GlobalLock(hglobal))) // Size of zero or lock succeeded: Include this format.
  360         {
  361             // Any changes made to how things are stored here should also be made to the size-estimation
  362             // phase so that space_needed matches what is done here:
  363             added_size = (VarSizeType)(sizeof(format) + sizeof(size) + size);
  364             actual_space_used += added_size;
  365             if (actual_space_used > space_needed) // Tolerate incorrect estimate by omitting formats that won't fit.
  366                 actual_space_used -= added_size;
  367             else
  368             {
  369                 *(UINT *)binary_contents = format;
  370                 binary_contents = (char *)binary_contents + sizeof(format);
  371                 *(SIZE_T *)binary_contents = size;
  372                 binary_contents = (char *)binary_contents + sizeof(size);
  373                 if (size)
  374                 {
  375                     memcpy(binary_contents, hglobal_locked, size);
  376                     binary_contents = (char *)binary_contents + size;
  377                 }
  378                 //else hglobal_locked is not valid, so don't reference it or unlock it.
  379             }
  380             if (size)
  381                 GlobalUnlock(hglobal); // hglobal not hglobal_locked.
  382         }
  383     }
  384     g_clip.Close();
  385     *(UINT *)binary_contents = 0; // Final termination (must be UINT, see above).
  386 
  387     if (aOutputVar)
  388     {
  389 #ifdef UNICODE
  390         // v1.1.16: Although it might change the behaviour of some scripts, it seems safer
  391         // to use the "rounded up" size than an odd byte count, which would cause the last
  392         // byte to be truncated due to integer division in Var::CharLength().
  393         if (actual_space_used & 1) // Odd number of bytes.
  394         {
  395             // Add one byte to form a complete WCHAR.  This should always be safe because
  396             // aOutputVar->SetCapacity() always allocates an even number of bytes.
  397             ((LPBYTE)binary_contents)[sizeof(UINT)] = 0; // binary_contents points at the "final termination" UINT.
  398             ++actual_space_used;
  399         }
  400 #endif
  401         aOutputVar->mByteLength = actual_space_used;
  402         aOutputVar->mAttrib |= VAR_ATTRIB_BINARY_CLIP; // VAR_ATTRIB_CONTENTS_OUT_OF_DATE and VAR_ATTRIB_CACHE were already removed by earlier call to SetCapacity().
  403     }
  404     else
  405         *aDataSize = (DWORD)actual_space_used;
  406     return OK;
  407 }
  408 
  409 
  410 
  411 ResultType Var::AssignBinaryClip(Var &aSourceVar)
  412 // Caller must ensure that this->Type() is VAR_NORMAL or VAR_CLIPBOARD (usually via load-time validation).
  413 // Caller must ensure that aSourceVar->Type()==VAR_NORMAL and aSourceVar->IsBinaryClip()==true.
  414 {
  415     if (mType == VAR_ALIAS)
  416         // For maintainability, it seems best not to use the following method:
  417         //    Var &var = *(mType == VAR_ALIAS ? mAliasFor : this);
  418         // If that were done, bugs would be easy to introduce in a long function like this one
  419         // if your forget at use the implicit "this" by accident.  So instead, just call self.
  420         return mAliasFor->AssignBinaryClip(aSourceVar);
  421 
  422     // Resolve early for maintainability.
  423     // Relies on the fact that aliases can't point to other aliases (enforced by UpdateAlias()).
  424     Var &source_var = (aSourceVar.mType == VAR_ALIAS) ? *aSourceVar.mAliasFor : aSourceVar;
  425     source_var.UpdateContents(); // Update mContents/mLength (probably not necessary because caller is supposed to ensure that aSourceVar->IsBinaryClip()==true).
  426 
  427     if (mType == VAR_NORMAL) // Copy a binary variable to another variable that isn't the clipboard.
  428     {
  429         if (this == &source_var) // i.e. source == destination.  Aliases were already resolved.
  430         {
  431             // No need to mark this var since it has obviously already been initialized (it contains a binary clip):
  432             //MarkInitialized();
  433             return OK;
  434         }
  435         if (!SetCapacity(source_var.mByteLength, true, false)) // source_var.mLength vs. Length() is okay (see above).
  436             return FAIL; // Above should have already reported the error.
  437         memcpy(mByteContents, source_var.mByteContents, source_var.mByteLength + sizeof(TCHAR)); // Add sizeof(TCHAR) not sizeof(format). Contents() vs. a variable for the same because mContents might have just changed due Assign() above.
  438         mAttrib |= VAR_ATTRIB_BINARY_CLIP; // VAR_ATTRIB_CACHE and VAR_ATTRIB_CONTENTS_OUT_OF_DATE were already removed by earlier call to Assign().
  439         return OK; // No need to call Close() in this case.
  440     }
  441 
  442     // SINCE ABOVE DIDN'T RETURN, A VARIABLE CONTAINING BINARY CLIPBOARD DATA IS BEING COPIED BACK ONTO THE CLIPBOARD.
  443     return SetClipboardAll(source_var.mByteContents, source_var.mByteLength);
  444 }
  445 
  446 ResultType Var::SetClipboardAll(void *aData, size_t aDataSize)
  447 {
  448     if (!g_clip.Open())
  449         return g_script.ScriptError(CANT_OPEN_CLIPBOARD_WRITE);
  450     EmptyClipboard(); // Failure is not checked for since it's probably impossible under these conditions.
  451 
  452     // In case the variable contents are incomplete or corrupted (such as having been read in from a
  453     // bad file with FileRead), prevent reading beyond the end of the variable:
  454     LPVOID next, binary_contents = aData;
  455     LPVOID binary_contents_max = (char *)binary_contents + aDataSize; // The last accessible byte, which should be the last byte of the (UINT)0 terminator.
  456     HGLOBAL hglobal;
  457     LPVOID hglobal_locked;
  458     UINT format;
  459     SIZE_T size;
  460 
  461     while ((next = (char *)binary_contents + sizeof(format)) <= binary_contents_max
  462         && (format = *(UINT *)binary_contents)) // Get the format.  Relies on short-circuit boolean order.
  463     {
  464         binary_contents = next;
  465         if ((next = (char *)binary_contents + sizeof(size)) > binary_contents_max)
  466             break;
  467         size = *(UINT *)binary_contents; // Get the size of this format's data.
  468         binary_contents = next;
  469         if ((next = (char *)binary_contents + size) > binary_contents_max)
  470             break;
  471         // v1.1.16: Always allocate a non-zero amount, since testing shows that SetClipboardData()
  472         // fails when passed a zero-length HGLOBAL, at least on Windows 8.  Zero-initialize using
  473         // GMEM_ZEROINIT since GlobalAlloc() might return a block larger than requested.  Although
  474         // it isn't necessarily safer (depending on what programs do with this format), it should
  475         // at least be more consistent than leaving it uninitialized, if anything ever uses it.
  476         if (   !(hglobal = GlobalAlloc(GMEM_MOVEABLE | GMEM_ZEROINIT, size + (size == 0)))   )
  477         {
  478             g_clip.Close();
  479             return g_script.ScriptError(ERR_OUTOFMEM); // Short msg since so rare.
  480         }
  481         if (size) // i.e. Don't try to lock memory of size zero.  It's not needed.
  482         {
  483             if (   !(hglobal_locked = GlobalLock(hglobal))   )
  484             {
  485                 GlobalFree(hglobal);
  486                 g_clip.Close();
  487                 return g_script.ScriptError(_T("GlobalLock")); // Short msg since so rare.
  488             }
  489             memcpy(hglobal_locked, binary_contents, size);
  490             GlobalUnlock(hglobal);
  491             binary_contents = next;
  492         }
  493         //else hglobal is just an empty format, but store it for completeness/accuracy (e.g. CF_BITMAP).
  494         SetClipboardData(format, hglobal); // The system now owns hglobal.
  495     }
  496 
  497     return g_clip.Close();
  498 }
  499 
  500 
  501 
  502 ResultType Var::AssignString(LPCTSTR aBuf, VarSizeType aLength, bool aExactSize, bool aObeyMaxMem)
  503 // Returns OK or FAIL.
  504 // If aBuf isn't NULL, caller must ensure that aLength is either VARSIZE_MAX (which tells us that the
  505 // entire strlen() of aBuf should be used) or an explicit length (can be zero) that the caller must
  506 // ensure is less than or equal to the total length of aBuf (if less, only a substring is copied).
  507 // If aBuf is NULL, the variable will be set up to handle a string of at least aLength
  508 // in length.  In addition, if the var is the clipboard, it will be prepared for writing.
  509 // Any existing contents of this variable will be destroyed regardless of whether aBuf is NULL.
  510 // Note that aBuf's memory can safely overlap with that of this->Contents() because in that case the
  511 // new length of the contents will always be less than or equal to the old length, and thus no
  512 // reallocation/expansion is needed (such an expansion would free the source before it could be
  513 // written to the destination).  This is because callers pass in an aBuf that is either:
  514 // 1) Between this->Contents() and its terminator.
  515 // 2) Equal to this->Contents() but with aLength passed in as shorter than this->Length().
  516 //
  517 // Caller can omit both params to set a var to be empty-string, but in that case, if the variable
  518 // is of large capacity, its memory will not be freed.  This is by design because it allows the
  519 // caller to exploit its knowledge of whether the var's large capacity is likely to be needed
  520 // again in the near future, thus reducing the expected amount of memory fragmentation.
  521 // To explicitly free the memory, use Assign("").
  522 {
  523     if (mType == VAR_ALIAS)
  524         // For maintainability, it seems best not to use the following method:
  525         //    Var &var = *(mType == VAR_ALIAS ? mAliasFor : this);
  526         // If that were done, bugs would be easy to introduce in a long function like this one
  527         // if your forget at use the implicit "this" by accident.  So instead, just call self.
  528         return mAliasFor->AssignString(aBuf, aLength, aExactSize, aObeyMaxMem);
  529 
  530     bool do_assign = true;        // Set defaults.
  531     bool free_it_if_large = true; //
  532     if (!aBuf)
  533         if (aLength == VARSIZE_MAX) // Caller omitted this param too, so it wants to assign empty string.
  534         {
  535             free_it_if_large = false;
  536             aLength = 0; // aBuf is set to "" further below.
  537         }
  538         else // Caller gave a NULL buffer to signal us to ensure the var is at least aLength in capacity.
  539             do_assign = false;
  540     else // Caller provided a non-NULL buffer.
  541         if (aLength == VARSIZE_MAX) // Caller wants us to determine its length.
  542             aLength = (mCharContents == aBuf) ? _CharLength() : (VarSizeType)_tcslen(aBuf); // v1.0.45: Added optimization check: (mContents == aBuf).  v1.1.09.03: Replaced CharLength() with _CharLength() to avoid updating contents (probably only applicable when aBuf == Var::sEmptyString).
  543         //else leave aLength as the caller-specified value in case it's explicitly shorter than the apparent length.
  544     if (!aBuf)
  545         aBuf = _T("");  // From here on, make sure it's the empty string for all uses (read-only empty string vs. sEmptyString seems more appropriate in this case).
  546 
  547     size_t space_needed = aLength + 1; // +1 for the zero terminator.
  548     size_t space_needed_in_bytes = space_needed * sizeof(TCHAR);
  549 
  550     if (mType == VAR_CLIPBOARD)
  551     {
  552         if (do_assign)
  553             // Just return the result of this.  Note: The clipboard var's attributes,
  554             // such as mLength, are not maintained because it's a variable whose
  555             // contents usually aren't under our control.
  556             return g_clip.Set(aBuf, aLength);
  557         else
  558             // We open it for write now, because some caller's don't call
  559             // this function to write to the contents of the var, they
  560             // do it themselves.  Note: Below call will have displayed
  561             // any error that occurred:
  562             return g_clip.PrepareForWrite(space_needed) ? OK : FAIL;
  563     }
  564 
  565     // Since above didn't return, this variable isn't the clipboard.
  566     if (space_needed_in_bytes > g_MaxVarCapacity && aObeyMaxMem // v1.0.43.03: aObeyMaxMem was added since some callers aren't supposed to obey it.
  567         && space_needed_in_bytes > mByteCapacity) // v1.1.05: Fixed to allow assignment if a prior VarSetCapacity set the capacity high enough.
  568         return g_script.ScriptError(ERR_MEM_LIMIT_REACHED);
  569 
  570     if (space_needed < 2) // Variable is being assigned the empty string (or a deref that resolves to it).
  571     {
  572         Free(free_it_if_large ? VAR_FREE_IF_LARGE : VAR_NEVER_FREE); // This also makes the variable blank and removes VAR_ATTRIB_OFTEN_REMOVED.
  573         return OK;
  574     }
  575 
  576     if (IsObject()) // L31: Release this variable's reference to its object.
  577         ReleaseObject();
  578 
  579     // The below is done regardless of whether the section that follows it fails and returns early because
  580     // it's the correct thing to do in all cases.
  581     // For simplicity, this is done unconditionally even though it should be needed only
  582     // when do_assign is true. It's the caller's responsibility to turn on the binary-clip
  583     // attribute (if appropriate) by calling Var::Close() with the right option.
  584     mAttrib &= ~(VAR_ATTRIB_OFTEN_REMOVED | VAR_ATTRIB_UNINITIALIZED);
  585     // HOWEVER, other things like making mLength 0 and mContents blank are not done here for performance
  586     // reasons (it seems too rare that early return/failure will occur below, since it's only due to
  587     // out-of-memory... and even if it does happen, there are probably no consequences to leaving the variable
  588     // the way it is now (rather than forcing it to be blank) since the script thread that caused the error
  589     // will be ended.
  590 
  591     if (space_needed_in_bytes > mByteCapacity)
  592     {
  593         size_t new_size; // Use a new name, rather than overloading space_needed, for maintainability.
  594         char *new_mem;
  595 
  596         switch (mHowAllocated)
  597         {
  598         case ALLOC_NONE:
  599         case ALLOC_SIMPLE:
  600             if (space_needed_in_bytes <= _TSIZE(MAX_ALLOC_SIMPLE))
  601             {
  602                 // v1.0.31: Conserve memory within large arrays by allowing elements of length 3 or 7, for such
  603                 // things as the storage of boolean values, or the storage of short numbers (it's best to use
  604                 // multiples of 4 for size due to byte alignment in SimpleHeap; e.g. lengths of 3 and 7).
  605                 // Because the above checked that space_needed > mCapacity, the capacity will increase but
  606                 // never decrease in this section, which prevent a memory leak by only ever wasting a maximum
  607                 // of 4+8+MAX_ALLOC_SIMPLE for each variable (and then only in the worst case -- in the average
  608                 // case, it saves memory by avoiding the overhead incurred for each separate malloc'd block).
  609                 if (space_needed_in_bytes <= _TSIZE(4)) // Even for aExactSize, it seems best to prevent variables from having only a zero terminator in them because that would usually waste 3 bytes due to byte alignment in SimpleHeap.
  610                     new_size = _TSIZE(4); // v1.0.45: Increased from 2 to 4 to exploit byte alignment in SimpleHeap.
  611                 else if (aExactSize) // Allows VarSetCapacity() to make more flexible use of SimpleHeap.
  612                     new_size = space_needed_in_bytes;
  613                 else
  614                 {
  615                     if (space_needed_in_bytes <= _TSIZE(8))
  616                         new_size = _TSIZE(8); // v1.0.45: Increased from 7 to 8 to exploit 32-bit alignment in SimpleHeap.
  617                     else // space_needed <= MAX_ALLOC_SIMPLE
  618                         new_size = _TSIZE(MAX_ALLOC_SIMPLE);
  619                 }
  620                 // In the case of mHowAllocated==ALLOC_SIMPLE, the following will allocate another block
  621                 // from SimpleHeap even though the var already had one. This is by design because it can
  622                 // happen only a limited number of times per variable. See comments further above for details.
  623                 if (   !(new_mem = (char *) SimpleHeap::Malloc(new_size))   )
  624                     return FAIL; // It already displayed the error. Leave all var members unchanged so that they're consistent with each other. Don't bother making the var blank and its length zero for reasons described higher above.
  625                 mHowAllocated = ALLOC_SIMPLE;  // In case it was previously ALLOC_NONE. This step must be done only after the alloc succeeded.
  626                 break;
  627             }
  628             // ** ELSE DON'T BREAK, JUST FALL THROUGH TO THE NEXT CASE. **
  629             // **
  630         case ALLOC_MALLOC: // Can also reach here by falling through from above.
  631             // This case can happen even if space_needed is less than MAX_ALLOC_SIMPLE
  632             // because once a var becomes ALLOC_MALLOC, it should never change to
  633             // one of the other alloc modes.  See comments higher above for explanation.
  634             new_size = space_needed_in_bytes; // Below relies on this being initialized unconditionally.
  635             if (!aExactSize)
  636             {
  637                 // Allow a little room for future expansion to cut down on the number of
  638                 // free's and malloc's we expect to have to do in the future for this var:
  639                 if (new_size < _TSIZE(16)) // v1.0.45.03: Added this new size to prevent all local variables in a recursive
  640                     new_size = _TSIZE(16); // function from having a minimum size of MAX_PATH.  16 seems like a good size because it holds nearly any number.  It seems counterproductive to go too small because each malloc, no matter how small, could have around 40 bytes of overhead.
  641                 else if (new_size < _TSIZE(MAX_PATH))
  642                     new_size = _TSIZE(MAX_PATH);  // An amount that will fit all standard filenames seems good.
  643                 else if (new_size < _TSIZE(160 * 1024)) // MAX_PATH to 160 KB or less -> 10% extra.
  644                     new_size = (size_t)(new_size * 1.1);
  645                 else if (new_size < _TSIZE(1600 * 1024))  // 160 to 1600 KB -> 16 KB extra
  646                     new_size += _TSIZE(16 * 1024);
  647                 else if (new_size < _TSIZE(6400 * 1024)) // 1600 to 6400 KB -> 1% extra
  648                     new_size += (new_size / 100); // Produces smaller code than (new_size * 1.01) and benchmarks the same.
  649                 else  // 6400 KB or more: Cap the extra margin at some reasonable compromise of speed vs. mem usage: 64 KB
  650                     new_size += _TSIZE(64 * 1024);
  651                 if (new_size > g_MaxVarCapacity && aObeyMaxMem) // v1.0.43.03: aObeyMaxMem was added since some callers aren't supposed to obey it.
  652                     new_size = g_MaxVarCapacity;  // which has already been verified to be enough.
  653             }
  654             //else space_needed was already verified higher above to be within bounds.
  655 
  656             // In case the old memory area is large, free it before allocating the new one.  This reduces
  657             // the peak memory load on the system and reduces the chance of an actual out-of-memory error.
  658             bool memory_was_freed;
  659             if (memory_was_freed = (mHowAllocated == ALLOC_MALLOC && mByteCapacity)) // Verified correct: 1) Both are checked because it might have fallen through from case ALLOC_SIMPLE; 2) mCapacity indicates for certain whether mContents contains the empty string.
  660                 free(mByteContents); // The other members are left temporarily out-of-sync for performance (they're resync'd only if an error occurs).
  661             //else mContents contains a "" or it points to memory on SimpleHeap, so don't attempt to free it.
  662 
  663             if (   (ptrdiff_t)new_size < 0 || !(new_mem = (char *)malloc(new_size))   ) // v1.0.44.10: Added a sanity limit of 2 GB so that small negatives like VarSetCapacity(Var, -2) [and perhaps other callers of this function] don't crash.
  664             {
  665                 if (memory_was_freed) // Resync members to reflect the fact that it was freed (it's done this way for performance).
  666                 {
  667                     mByteCapacity = 0;             // Invariant: Anyone setting mCapacity to 0 must also set
  668                     mCharContents = sEmptyString;  // mContents to the empty string.
  669                 }
  670                 else
  671                 {
  672                     // IMPORTANT: It's the empty string (a constant) or it points to memory on SimpleHeap, so don't
  673                     // change mContents/Capacity (that would cause a memory leak for reasons described elsewhere).
  674                     // Make the var empty for the following reasons:
  675                     //  1) This condition could be caused by the script requesting a very high (possibly invalid)
  676                     //     capacity with VarSetCapacity().  The script might be handling the failure using TRY/CATCH,
  677                     //     so we want the result to be sane.
  678                     //  2) It's safer and more maintainable.  For instance, VarSetCapacity() sets length to 0, which
  679                     //     can produce bad/undefined results if there is no null-terminator at mCharContents[Length()]
  680                     //     as some other parts of the code assume.
  681                     //  3) It's more consistent.  If this var contained a binary number or object, it has already
  682                     //     been cleared by "mAttrib &=" above.
  683                     *mCharContents = '\0'; // If it's sEmptyString, that's okay too because it's writable.
  684                 }
  685                 mByteLength = 0; // mAttrib was already updated higher above.
  686                 return g_script.ScriptError(ERR_OUTOFMEM); // since an error is most likely to occur at runtime.
  687             }
  688 
  689             // Below is necessary because it might have fallen through from case ALLOC_SIMPLE.
  690             // This step must be done only after the alloc succeeded (because otherwise, want to keep it
  691             // set to ALLOC_SIMPLE (fall-through), if that's what it was).
  692             mHowAllocated = ALLOC_MALLOC;
  693             break;
  694         } // switch()
  695 
  696         // Since above didn't return, the alloc succeeded.  Because that's true, all the members (except those
  697         // set in their sections above) are updated together so that they stay consistent with each other:
  698         mByteContents = new_mem;
  699         mByteCapacity = (VarSizeType)new_size;
  700         mAttrib &= ~VAR_ATTRIB_CACHE_DISABLED; // If the script previously took the address of this variable, that address is no longer valid; so there is no need to protect against the script directly accessing this variable. This is never reached for VAR_CLIPBOARD, so that isn't checked.
  701     } // if (space_needed > mCapacity)
  702 
  703     if (do_assign)
  704     {
  705         // Above has ensured that space_needed is either strlen(aBuf)-1 or the length of some
  706         // substring within aBuf starting at aBuf.  However, aBuf might overlap mContents or
  707         // even be the same memory address (due to something like GlobalVar := YieldGlobalVar(),
  708         // in which case ACT_ASSIGNEXPR calls us to assign GlobalVar to GlobalVar).
  709         if (mCharContents != aBuf)
  710         {
  711             // Don't use strlcpy() or such because:
  712             // 1) Caller might have specified that only part of aBuf's total length should be copied.
  713             // 2) mContents and aBuf might overlap (see above comment), in which case strcpy()'s result
  714             //    is undefined, but memmove() is guaranteed to work (and performs about the same).
  715             tmemmove(mCharContents, aBuf, aLength); // Some callers such as RegEx routines might rely on this copying binary zeroes over rather than stopping at the first binary zero.
  716         }
  717         //else nothing needs to be done since source and target are identical.  Some callers probably rely on
  718         // this optimization.
  719         mCharContents[aLength] = '\0'; // v1.0.45: This is now done unconditionally in case caller wants to shorten a variable's existing contents (no known callers do this, but it helps robustness).
  720     }
  721     else // Caller only wanted the variable resized as a preparation for something it will do later.
  722     {
  723         // Init for greater robustness/safety (the ongoing conflict between robustness/redundancy and performance).
  724         // This has been in effect for so long that some callers probably rely on it.
  725         *mCharContents = '\0'; // If it's sEmptyString, that's okay too because it's writable.
  726         // We've done everything except the actual assignment.  Let the caller handle that.
  727         // Also, the length will be set below to the expected length in case the caller
  728         // doesn't override this.
  729         // Below: Already verified that the length value will fit into VarSizeType.
  730     }
  731 
  732     // Writing to union is safe because above already ensured that "this" isn't an alias.
  733     mByteLength = aLength * sizeof(TCHAR); // aLength was verified accurate higher above.
  734     return OK;
  735 }
  736 
  737 
  738 
  739 ResultType Var::AssignSkipAddRef(IObject *aValueToAssign)
  740 {
  741     // Relies on the fact that aliases can't point to other aliases (enforced by UpdateAlias()).
  742     Var &var = *(mType == VAR_ALIAS ? mAliasFor : this);
  743 
  744     if (var.mType != VAR_NORMAL)
  745     {
  746         aValueToAssign->Release();
  747         return g_script.ScriptError(ERR_INVALID_VALUE, _T("An object."));
  748     }
  749 
  750     var.Free(); // If var contains an object, this will Release() it.  It will also clear any string contents and free memory if appropriate.
  751         
  752     var.mObject = aValueToAssign;
  753         
  754     // Already done by Free() above:
  755     //mAttrib &= ~(VAR_ATTRIB_OFTEN_REMOVED | VAR_ATTRIB_UNINITIALIZED);
  756 
  757     // Mark this variable to indicate it contains an object.
  758     // Currently nothing should attempt to cache a number in a variable which contains an object, but it may become
  759     // possible if a "default property" mechanism is introduced for implicitly converting an object to a string/number.
  760     // There are at least two ways the caching mechanism could conflict with objects:
  761     //  1) Caching a number would overwrite mObject.
  762     //  2) Caching a number or flagging the variable as "non-numeric" would give incorrect results if the object's
  763     //     default property can implicitly change (and this change cannot be detected in order to invalidate the cache).
  764     // Including VAR_ATTRIB_CACHE_DISABLED below should prevent caching from ever occurring for a variable containing an object.
  765     // Including VAR_ATTRIB_NOT_NUMERIC below allows IsNonBlankIntegerOrFloat to return early if it is passed an object.
  766     var.mAttrib |= VAR_ATTRIB_OBJECT | VAR_ATTRIB_CACHE_DISABLED | VAR_ATTRIB_NOT_NUMERIC;
  767 
  768     return OK;
  769 }
  770 
  771 
  772 
  773 VarSizeType Var::Get(LPTSTR aBuf)
  774 // Returns the length of this var's contents.  In addition, if aBuf isn't NULL, it will copy the contents into aBuf.
  775 {
  776     // Aliases: VAR_ALIAS is checked and handled further down than in most other functions.
  777     //
  778     // For v1.0.25, don't do the following because in some cases the existing contents of aBuf will not
  779     // be altered.  Instead, it will be set to blank as needed further below.
  780     //if (aBuf) *aBuf = '\0';  // Init early to get it out of the way, in case of early return.
  781     DWORD result;
  782     VarSizeType length;
  783     TCHAR buf_temp[1]; // Just a fake buffer to pass to some API functions in lieu of a NULL, to avoid any chance of misbehavior. Keep the size at 1 so that API functions will always fail to copy to buf.
  784 
  785     switch(mType)
  786     {
  787     case VAR_NORMAL: // Listed first for performance.
  788         UpdateContents();  // Update mContents and mLength, if necessary.
  789         if (!g_NoEnv && !mByteLength) // If auto-env retrieval is on and the var is empty, check to see if it's really an env. var.
  790         {
  791             // Regardless of whether aBuf is NULL or not, we don't know at this stage
  792             // whether mName is the name of a valid environment variable.  Therefore,
  793             // GetEnvironmentVariable() is currently called once in the case where
  794             // aBuf is NULL and twice in the case where it's not.  There may be some
  795             // way to reduce it to one call always, but that is an optimization for
  796             // the future.  Another reason: Calling it twice seems safer, because we can't
  797             // be completely sure that it wouldn't act on our (possibly undersized) aBuf
  798             // buffer even if it doesn't find the env. var.
  799             // UPDATE: v1.0.36.02: It turns out that GetEnvironmentVariable() is a fairly
  800             // high overhead call. To improve the speed of accessing blank variables that
  801             // aren't environment variables (and most aren't), cached_empty_var is used
  802             // to indicate that the previous size-estimation call to us yielded "no such
  803             // environment variable" so that the upcoming get-contents call to us can avoid
  804             // calling GetEnvironmentVariable() again.  Testing shows that this doubles
  805             // the speed of a simple loop that accesses an empty variable such as the following:
  806             // SetBatchLines -1
  807             // Loop 500000
  808             //    if Var = Test
  809             //    ...
  810             static Var *cached_empty_var = NULL; // Doubles the speed of accessing empty variables that aren't environment variables (i.e. most of them).
  811             if (!(cached_empty_var == this && aBuf) && (result = GetEnvironmentVariable(mName, buf_temp, 0)))
  812             {
  813                 // This env. var exists.
  814                 cached_empty_var = NULL; // i.e. one use only to avoid cache from hiding the fact that an environment variable has newly come into existence since the previous call.
  815                 if (aBuf)
  816                 {
  817                     if (g_Warn_UseEnv)
  818                         g_script.ScriptWarning(g_Warn_UseEnv, WARNING_USE_ENV_VARIABLE, mName);
  819                     return GetEnvVarReliable(mName, aBuf); // The caller has ensured, probably via previous call to this function with aBuf == NULL, that aBuf is large enough to hold the result.
  820                 }
  821                 return result - 1;  // -1 because GetEnvironmentVariable() returns total size needed when called that way.
  822             }
  823             else // No matching env. var. or the cache indicates that GetEnvironmentVariable() need not be called.
  824             {
  825                 if (aBuf)
  826                 {
  827                     MaybeWarnUninitialized();
  828                     *aBuf = '\0';
  829                     cached_empty_var = NULL; // i.e. one use only to avoid cache from hiding the fact that an environment variable has newly come into existence since the previous call.
  830                 }
  831                 else // Size estimation phase: Since there is no such env. var., flag it for the upcoming get-contents phase.
  832                     cached_empty_var = this;
  833                 return 0;
  834             }
  835         }
  836         length = _CharLength();
  837 
  838         // Otherwise (since above didn't return), it's not an environment variable (or it is, but there's
  839         // a script variable of non-zero length that's eclipsing it).
  840         if (!aBuf)
  841             return length;
  842         else // Caller provider buffer, so if mLength is zero, just make aBuf empty now and return early (for performance).
  843             if (!mByteLength)
  844             {
  845                 MaybeWarnUninitialized();
  846                 *aBuf = '\0';
  847                 return 0;
  848             }
  849             //else continue on below.
  850         if (aBuf == mCharContents)
  851             // When we're called from ExpandArg() that was called from PerformAssign(), PerformAssign()
  852             // relies on this check to avoid the overhead of copying a variables contents onto itself.
  853             return length;
  854         else if (mByteLength < 100000)
  855         {
  856             // Copy the var contents into aBuf.  Although a little bit slower than CopyMemory() for large
  857             // variables (say, over 100K), this loop seems much faster for small ones, which is the typical
  858             // case.  Also of note is that this code section is the main bottleneck for scripts that manipulate
  859             // large variables, such as this:
  860             //start_time = %A_TICKCOUNT%
  861             //my = 0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789
  862             //tempvar =
  863             //loop, 2000
  864             //  tempvar = %tempvar%%My%
  865             //elapsed_time = %A_TICKCOUNT%
  866             //elapsed_time -= %start_time%
  867             //msgbox, elapsed_time = %elapsed_time%
  868             //return
  869             for (LPTSTR cp = mCharContents; *cp; *aBuf++ = *cp++); // UpdateContents() was already called higher above to update mContents.
  870             *aBuf = '\0';
  871         }
  872         else
  873         {
  874             CopyMemory(aBuf, mByteContents, mByteLength); // Faster for large vars, but large vars aren't typical.
  875             aBuf[length] = '\0'; // This is done as a step separate from above in case mLength is inaccurate (e.g. due to script's improper use of DllCall).
  876         }
  877         return length;
  878 
  879     case VAR_ALIAS:
  880         // For maintainability, it seems best not to use the following method:
  881         //    Var &var = *(mType == VAR_ALIAS ? mAliasFor : this);
  882         // If that were done, bugs would be easy to introduce in a long function like this one
  883         // if your forget at use the implicit "this" by accident.  So instead, just call self.
  884         return mAliasFor->Get(aBuf);
  885 
  886     // Built-in vars with volatile contents:
  887     case VAR_CLIPBOARD:
  888     {
  889         length = (VarSizeType)g_clip.Get(aBuf); // It will also copy into aBuf if it's non-NULL.
  890         if (length == CLIPBOARD_FAILURE)
  891         {
  892             // Above already displayed the error, so just return.
  893             // If we were called only to determine the size, the
  894             // next call to g_clip.Get() will not put anything into
  895             // aBuf (it will either fail again, or it will return
  896             // a length of zero due to the clipboard not already
  897             // being open & ready), so there's no danger of future
  898             // buffer overflows as a result of returning zero here.
  899             // Also, due to this function's return type, there's
  900             // no easy way to terminate the current hotkey
  901             // subroutine (or entire script) due to this error.
  902             // However, due to the fact that multiple attempts
  903             // are made to open the clipboard, failure should
  904             // be extremely rare.  And the user will be notified
  905             // with a MsgBox anyway, during which the subroutine
  906             // will be suspended:
  907             length = 0;
  908         }
  909         if (aBuf)
  910             aBuf[length] = '\0'; // Might not be necessary, but kept in case it ever is.
  911         return length;
  912     }
  913 
  914     case VAR_CLIPBOARDALL: // There's a slight chance this case is never executed; but even if true, it should be kept for maintainability.
  915         // This variable is directly handled at a higher level.  As documented, any use of ClipboardAll outside of
  916         // the supported modes yields an empty string.
  917         if (aBuf)
  918             *aBuf = '\0';
  919         return 0;
  920 
  921     default: // v1.0.46.16: VAR_BUILTIN: Call the function associated with this variable to retrieve its contents.  This change reduced uncompressed coded size by 6 KB.
  922         return mBIV(aBuf, mName);
  923     } // switch(mType)
  924 }
  925 
  926 
  927 
  928 void Var::Free(int aWhenToFree, bool aExcludeAliasesAndRequireInit)
  929 // The name "Free" is a little misleading because this function:
  930 // ALWAYS sets the variable to be blank (except for static variables and aExcludeAliases==true).
  931 // BUT ONLY SOMETIMES frees the memory, depending on various factors described further below.
  932 // Caller must be aware that ALLOC_SIMPLE (due to its nature) is never freed.
  933 // aExcludeAliasesAndRequireInit may be split into two if any caller ever wants to pass
  934 // true for one and not the other (currently there is only one caller who passes true).
  935 {
  936     // Not checked because even if it's not VAR_NORMAL, there are few if any consequences to continuing.
  937     //if (mType != VAR_NORMAL) // For robustness, since callers generally shouldn't call it this way.
  938     //  return;
  939 
  940     if (mType == VAR_ALIAS) // For simplicity and reduced code size, just make a recursive call to self.
  941     {
  942         if (!aExcludeAliasesAndRequireInit)
  943             // For maintainability, it seems best not to use the following method:
  944             //    Var &var = *(mType == VAR_ALIAS ? mAliasFor : this);
  945             // If that were done, bugs would be easy to introduce in a long function like this one
  946             // if your forget at use the implicit "this" by accident.  So instead, just call self.
  947             mAliasFor->Free(aWhenToFree);
  948         //else caller didn't want the target of the alias freed, so do nothing.
  949         return;
  950     }
  951 
  952     // Must check this one first because caller relies not only on var not being freed in this case,
  953     // but also on its contents not being set to an empty string:
  954     if (aWhenToFree == VAR_ALWAYS_FREE_BUT_EXCLUDE_STATIC && IsStatic())
  955         return; // This is the only case in which the variable ISN'T made blank.
  956 
  957     if (IsObject()) // L31: Release this variable's reference to its object.
  958         ReleaseObject();
  959 
  960     mByteLength = 0; // Writing to union is safe because above already ensured that "this" isn't an alias.
  961     // Even if it isn't free'd, variable will be made blank.  So it seems proper to always remove
  962     // the binary_clip attribute (since it can't be used that way after it's been made blank) and
  963     // the uninitialized attribute (since *we* are initializing it).  Some callers may rely on us
  964     // removing these attributes:
  965     mAttrib &= ~(VAR_ATTRIB_OFTEN_REMOVED | VAR_ATTRIB_UNINITIALIZED);
  966 
  967     if (aExcludeAliasesAndRequireInit)
  968         // Caller requires this var to be considered uninitialized from now on.  This attribute may
  969         // have been removed above, but there was no cost involved.  It might not have been set in
  970         // the first place, so we must add it here anyway:
  971         mAttrib |= VAR_ATTRIB_UNINITIALIZED;
  972 
  973     switch (mHowAllocated)
  974     {
  975     // Shouldn't be necessary to check the following because by definition, ALLOC_NONE
  976     // means mContents==sEmptyString (this policy is enforced in other places).
  977     //
  978     //case ALLOC_NONE:
  979     //  mContents = sEmptyString;
  980     //  break;
  981 
  982     case ALLOC_SIMPLE:
  983         // Don't set to sEmptyString because then we'd have a memory leak.  i.e. once a var becomes
  984         // ALLOC_SIMPLE, it should never become ALLOC_NONE again (though it can become ALLOC_MALLOC).
  985         *mCharContents = '\0';
  986         break;
  987 
  988     case ALLOC_MALLOC:
  989         // Setting a var whose contents are very large to be nothing or blank is currently the
  990         // only way to free up the memory of that var.  Shrinking it dynamically seems like it
  991         // might introduce too much memory fragmentation and overhead (since in many cases,
  992         // it would likely need to grow back to its former size in the near future).  So we
  993         // only free relatively large vars:
  994         if (mByteCapacity)
  995         {
  996             // aWhenToFree==VAR_FREE_IF_LARGE: the memory is not freed if it is a small area because
  997             // it might help reduce memory fragmentation and improve performance in cases where
  998             // the memory will soon be needed again (in which case one free+malloc is saved).
  999             if (   aWhenToFree < VAR_ALWAYS_FREE_LAST  // Fixed for v1.0.40.07 to prevent memory leak in recursive script-function calls.
 1000                 || aWhenToFree == VAR_FREE_IF_LARGE && mByteCapacity > (4 * 1024)   )
 1001             {
 1002                 free(mByteContents);
 1003                 mByteCapacity = 0;             // Invariant: Anyone setting mCapacity to 0 must also set
 1004                 mCharContents = sEmptyString;  // mContents to the empty string.
 1005                 mAttrib &= ~VAR_ATTRIB_CACHE_DISABLED; // If the script previously took the address of this variable, that address is no longer valid; so there is no need to protect against the script directly accessing this variable. This is never reached for VAR_CLIPBOARD, so that isn't checked.
 1006                 // BUT DON'T CHANGE mHowAllocated to ALLOC_NONE (see comments further below).
 1007             }
 1008             else // Don't actually free it, but make it blank (callers rely on this).
 1009                 *mCharContents = '\0';
 1010         }
 1011         //else mCapacity==0, so mContents is already the empty string, so don't attempt to free
 1012         // it or assign to it. It was the responsibility of whoever set mCapacity to 0 to ensure mContents
 1013         // was set properly (which is why it's not done here).
 1014 
 1015         // But do not change mHowAllocated to be ALLOC_NONE because it would cause a
 1016         // a memory leak in this sequence of events:
 1017         // var1 is assigned something short enough to make it ALLOC_SIMPLE
 1018         // var1 is assigned something large enough to require malloc()
 1019         // var1 is set to empty string and its mem is thus free()'d by the above.
 1020         // var1 is once again assigned something short enough to make it ALLOC_SIMPLE
 1021         // The last step above would be a problem because the 2nd ALLOC_SIMPLE can't
 1022         // reclaim the spot in SimpleHeap that had been in use by the first.  In other
 1023         // words, when a var makes the transition from ALLOC_SIMPLE to ALLOC_MALLOC,
 1024         // its ALLOC_SIMPLE memory is lost to the system until the program exits.
 1025         // But since this loss occurs at most once per distinct variable name,
 1026         // it's not considered a memory leak because the loss can't exceed a fixed
 1027         // amount regardless of how long the program runs.  The reason for all of this
 1028         // is that allocating dynamic memory is costly: it causes system memory fragmentation,
 1029         // (especially if a var were to be malloc'd and free'd thousands of times in a loop)
 1030         // and small-sized mallocs have a large overhead: it's been said that every block
 1031         // of dynamic mem, even those of size 1 or 2, incurs about 40 bytes of overhead
 1032         // (and testing of SimpleHeap supports this).
 1033         // UPDATE: Yes it's true that a script could create an unlimited number of new variables
 1034         // by constantly using different dynamic names when creating them.  But it's still supportable
 1035         // that there's no memory leak because even if the worst-case series of events mentioned
 1036         // higher above occurs for every variable, only a fixed amount of memory is ever lost per
 1037         // variable.  So you could think of the lost memory as part of the basic overhead of creating
 1038         // a variable (since variables are never truly destroyed, just their contents freed).
 1039         // The odds against all of these worst-case factors occurring simultaneously in anything other
 1040         // than a theoretical test script seem nearly astronomical.
 1041         break;
 1042     } // switch()
 1043 }
 1044 
 1045 
 1046 
 1047 ResultType Var::AppendIfRoom(LPTSTR aStr, VarSizeType aLength)
 1048 // Returns OK if there's room enough to append aStr and it succeeds.
 1049 // Returns FAIL otherwise (also returns FAIL for VAR_CLIPBOARD).
 1050 // Environment variables aren't supported here; instead, aStr is appended directly onto the actual/internal
 1051 // contents of the "this" variable.
 1052 {
 1053     // Relies on the fact that aliases can't point to other aliases (enforced by UpdateAlias()):
 1054     Var &var = *(mType == VAR_ALIAS ? mAliasFor : this);
 1055     if (var.mType != VAR_NORMAL) // e.g. VAR_CLIPBOARD. Some callers do call it this way, but even if not it should be kept for maintainability.
 1056         return FAIL; // CHECK THIS FIRST, BEFORE BELOW, BECAUSE CALLERS ALWAYS WANT IT TO BE A FAILURE.
 1057     if (!aLength) // Consider the appending of nothing to be a success.
 1058         return OK;
 1059     VarSizeType var_length = var.LengthIgnoreBinaryClip(); // Get the apparent length because one caller is a concat that wants consistent behavior of the .= operator regardless of whether this shortcut succeeds or not.
 1060     VarSizeType new_length = var_length + aLength;
 1061     if (new_length >= var._CharCapacity()) // Not enough room.
 1062         return FAIL;
 1063     tmemmove(var.mCharContents + var_length, aStr, aLength);  // mContents was updated via LengthIgnoreBinaryClip() above. Use memmove() vs. memcpy() in case there's any overlap between source and dest.
 1064     var.mCharContents[new_length] = '\0'; // Terminate it as a separate step in case caller passed a length shorter than the apparent length of aStr.
 1065     var.mByteLength = new_length * sizeof(TCHAR);
 1066     if (IsObject()) // L31: Release this variable's reference to its object.
 1067         ReleaseObject();
 1068     // If this is a binary-clip variable, appending has probably "corrupted" it; so don't allow it to ever be
 1069     // put back onto the clipboard as binary data (the routine that does that is designed to detect corruption,
 1070     // but it might not be perfect since corruption is so rare).  Also remove the other flags that are no longer
 1071     // appropriate:
 1072     var.mAttrib &= ~VAR_ATTRIB_OFTEN_REMOVED; // This also removes VAR_ATTRIB_NOT_NUMERIC because appending some digits to an empty variable would make it numeric.
 1073     return OK;
 1074 }
 1075 
 1076 
 1077 
 1078 void Var::AcceptNewMem(LPTSTR aNewMem, VarSizeType aLength)
 1079 // Caller provides a new malloc'd memory block (currently must be non-NULL).  That block and its
 1080 // contents are directly hung onto this variable in place of its old block, which is freed (except
 1081 // in the case of VAR_CLIPBOARD, in which case the memory is copied onto the clipboard then freed).
 1082 // Caller must ensure that mType == VAR_NORMAL or VAR_CLIPBOARD.
 1083 // This function was added in v1.0.45 to aid callers in improving performance.
 1084 {
 1085     // Relies on the fact that aliases can't point to other aliases (enforced by UpdateAlias()).
 1086     Var &var = *(mType == VAR_ALIAS ? mAliasFor : this);
 1087     if (var.mType == VAR_CLIPBOARD)
 1088     {
 1089         var.Assign(aNewMem, aLength); // Clipboard requires GlobalAlloc memory so can't directly accept aNewMem.  So just copy it the normal way.
 1090         free(aNewMem); // Caller gave it to us to take charge of, but we have no further use for it.
 1091     }
 1092     else // VAR_NORMAL
 1093     {
 1094         var.Free(VAR_ALWAYS_FREE); // Release the variable's old memory. This also removes flags VAR_ATTRIB_OFTEN_REMOVED.
 1095         var.mHowAllocated = ALLOC_MALLOC; // Must always be this type to avoid complications and possible memory leaks.
 1096         var.mByteContents = (char *) aNewMem;
 1097         var.mByteLength = aLength * sizeof(TCHAR);
 1098         ASSERT( var.mByteLength + sizeof(TCHAR) <= _msize(aNewMem) );
 1099         var.mByteCapacity = (VarSizeType)_msize(aNewMem); // Get actual capacity in case it's a lot bigger than aLength+1. _msize() is only about 36 bytes of code and probably a very fast call.
 1100         var.mAttrib &= ~VAR_ATTRIB_CACHE_DISABLED; // This isn't always done by Free() above, so do it here in case it wasn't (it seems too unlikely to have to check whether aNewMem==the_old_mem_address).  Reason: If the script previously took the address of this variable, that address is no longer valid; so there is no need to protect against the script directly accessing this variable.
 1101         // Already done by Free() above:
 1102         //mAttrib &= ~(VAR_ATTRIB_OFTEN_REMOVED | VAR_ATTRIB_UNINITIALIZED); // New memory is always non-binary-clip.  A new parameter could be added to change this if it's ever needed.
 1103 
 1104         // Shrink the memory if there's a lot of wasted space because the extra capacity is seldom utilized
 1105         // in real-world scripts.
 1106         // A simple rule seems best because shrinking is probably fast regardless of the sizes involved,
 1107         // plus and there's considerable rarity to ever needing capacity beyond what's in a variable
 1108         // (concat/append is one example).  This will leave a large percentage of extra space in small variables,
 1109         // but in those rare cases when a script needs to create thousands of such variables, there may be a
 1110         // current or future way to shrink an existing variable to contain only its current length, such as
 1111         // VarShrink().
 1112         if (var.mByteCapacity - var.mByteLength > 64)
 1113         {
 1114             var.mByteCapacity = var.mByteLength + sizeof(TCHAR); // This will become the new capacity.
 1115             // _expand() is only about 75 bytes of uncompressed code size and probably performs very quickly
 1116             // when shrinking.  Also, MSDN implies that when shrinking, failure won't happen unless something
 1117             // is terribly wrong (e.g. corrupted heap).  But for robustness it is checked anyway:
 1118             if (   !(var.mByteContents = (char *)_expand(var.mByteContents, var.mByteCapacity))   )
 1119             {
 1120                 var.mByteLength = 0;
 1121                 var.mByteCapacity = 0;
 1122             }
 1123         }
 1124     }
 1125 }
 1126 
 1127 
 1128 
 1129 void Var::SetLengthFromContents()
 1130 // Function added in v1.0.43.06.  It updates the mLength member to reflect the actual current length of mContents.
 1131 // Caller must ensure that Type() is VAR_NORMAL.
 1132 {
 1133     // Relies on the fact that aliases can't point to other aliases (enforced by UpdateAlias()).
 1134     Var &var = *(mType == VAR_ALIAS ? mAliasFor : this);
 1135     VarSizeType capacity = var.Capacity();
 1136     var.UpdateContents(); // Ensure mContents and mLength are up-to-date.
 1137     if (capacity > 0)
 1138     {
 1139         var.mCharContents[capacity - 1] = '\0';  // Caller wants us to ensure it's terminated, to avoid crashing strlen() below.
 1140         var.mByteLength = ((VarSizeType)_tcslen(var.mCharContents)) * sizeof(TCHAR);
 1141     }
 1142     //else it has no capacity, so do nothing (it could also be a reserved/built-in variable).
 1143 }
 1144 
 1145 
 1146 
 1147 ResultType Var::BackupFunctionVars(Func &aFunc, VarBkp *&aVarBackup, int &aVarBackupCount)
 1148 // All parameters except the first are output parameters that are set for our caller (though caller
 1149 // is responsible for having initialized aVarBackup to NULL).
 1150 // If there is nothing to backup, only the aVarBackupCount is changed (to zero).
 1151 // Returns OK or FAIL.
 1152 {
 1153     if (   !(aVarBackupCount = aFunc.mVarCount + aFunc.mLazyVarCount)   )  // Nothing needs to be backed up.
 1154         return OK; // Leave aVarBackup set to NULL as set by the caller.
 1155 
 1156     // NOTES ABOUT MALLOC(): Apparently, the implementation of malloc() is quite good, at least for small blocks
 1157     // needed to back up 50 or less variables.  It nearly as fast as alloca(), at least when the system
 1158     // isn't under load and has the memory to spare without swapping.  Therefore, the attempt to use alloca to
 1159     // speed up recursive script-functions didn't result in enough of a speed-up (only 1 to 5%) to be worth the
 1160     // added complexity.
 1161     // Since Var is not a POD struct (it contains private members, a custom constructor, etc.), the VarBkp
 1162     // POD struct is used to hold the backup because it's probably better performance than using Var's
 1163     // constructor to create each backup array element.
 1164     if (   !(aVarBackup = (VarBkp *)malloc(aVarBackupCount * sizeof(VarBkp)))   ) // Caller will take care of freeing it.
 1165         return FAIL;
 1166 
 1167     int i;
 1168     aVarBackupCount = 0;  // Init only once prior to both loops. aVarBackupCount is being "overloaded" to track the current item in aVarBackup, BUT ALSO its being updated to an actual count in case some statics are omitted from the array.
 1169 
 1170     // Note that Backup() does not make the variable empty after backing it up because that is something
 1171     // that must be done by our caller at a later stage.
 1172     for (i = 0; i < aFunc.mVarCount; ++i)
 1173         if (!aFunc.mVar[i]->IsStatic()) // Don't bother backing up statics because they won't need to be restored.
 1174             aFunc.mVar[i]->Backup(aVarBackup[aVarBackupCount++]);
 1175     for (i = 0; i < aFunc.mLazyVarCount; ++i)
 1176         if (!aFunc.mLazyVar[i]->IsStatic()) // Don't bother backing up statics because they won't need to be restored.
 1177             aFunc.mLazyVar[i]->Backup(aVarBackup[aVarBackupCount++]);
 1178     return OK;
 1179 }
 1180 
 1181 
 1182 
 1183 void Var::Backup(VarBkp &aVarBkp)
 1184 // Caller must not call this function for static variables because it's not equipped to deal with them
 1185 // (they don't need to be backed up or restored anyway).
 1186 // This method is used rather than struct copy (=) because it's of expected higher performance than
 1187 // using the Var::constructor to make a copy of each var.  Also note that something like memcpy()
 1188 // can't be used on Var objects since they're not POD (e.g. they have a constructor and they have
 1189 // private members).
 1190 {
 1191     aVarBkp.mVar = this; // Allows the restoration process to always know its target without searching.
 1192     aVarBkp.mByteContents = mByteContents;
 1193     aVarBkp.mContentsInt64 = mContentsInt64; // This also copies the other member of the union: mContentsDouble.
 1194     aVarBkp.mByteLength = mByteLength; // Since it's a union, it might actually be backing up mAliasFor (happens at least for recursive functions that pass parameters ByRef).
 1195     aVarBkp.mByteCapacity = mByteCapacity;
 1196     aVarBkp.mHowAllocated = mHowAllocated; // This might be ALLOC_SIMPLE or ALLOC_NONE if backed up variable was at the lowest layer of the call stack.
 1197     aVarBkp.mAttrib = mAttrib;
 1198     aVarBkp.mType = mType; // Fix for v1.0.47.06: Must also back up and restore mType in case an optional ByRef parameter is omitted by one call by specified by another thread that interrupts the first thread's call.
 1199     // Once the backup is made, Free() is not called because the whole point of the backup is to
 1200     // preserve the original memory/contents of each variable.  Instead, clear the variable
 1201     // completely and set it up to become ALLOC_MALLOC in case anything actually winds up using
 1202     // the variable prior to the restoration of the backup.  In other words, ALLOC_SIMPLE and NONE
 1203     // retained (if present) because that would cause a memory leak when multiple layers are all
 1204     // allowed to use ALLOC_SIMPLE yet none are ever able to free it (the bottommost layer is
 1205     // allowed to use ALLOC_SIMPLE because that's a fixed/constant amount of memory gets freed
 1206     // when the program exits).
 1207     // Now reset this variable (caller has ensured it's non-static) to create a "new layer" for it, keeping
 1208     // its backup intact but allowing this variable (or formal parameter) to be given a new value in the future:
 1209     mByteCapacity = 0;             // Invariant: Anyone setting mCapacity to 0 must also set...
 1210     mCharContents = sEmptyString;  // ...mContents to the empty string.
 1211     if (mType != VAR_ALIAS) // Fix for v1.0.42.07: Don't reset mLength if the other member of the union is in effect.
 1212         mByteLength = 0;        // Otherwise, functions that recursively pass ByRef parameters can crash because mType stays as VAR_ALIAS.
 1213     mHowAllocated = ALLOC_MALLOC; // Never NONE because that would permit SIMPLE. See comments higher above.
 1214     //mAttrib &= ~(VAR_ATTRIB_OFTEN_REMOVED | VAR_ATTRIB_CACHE_DISABLED | VAR_ATTRIB_OBJECT);
 1215     // Above: Removing VAR_ATTRIB_CACHE_DISABLED doesn't cost anything in performance and might help cases where
 1216     // a recursively-called function does numeric, cache-only operations on a variable that has zero capacity.
 1217     // Since we're removing every attribute except the one we want to add, just reset mAttrib:
 1218     mAttrib = VAR_ATTRIB_UNINITIALIZED; // The function's new recursion layer should consider this var uninitialized, even if it was initialized by the previous layer.
 1219 }
 1220 
 1221 
 1222 
 1223 void Var::Restore(VarBkp &aVarBkp)
 1224 {
 1225     mByteContents = aVarBkp.mByteContents;
 1226     mContentsInt64 = aVarBkp.mContentsInt64; // This also copies the other members of the union: mContentsDouble, mObject.
 1227     mByteLength = aVarBkp.mByteLength; // Since it's a union, it might actually be restoring mAliasFor, which is desired.
 1228     mByteCapacity = aVarBkp.mByteCapacity;
 1229     mHowAllocated = aVarBkp.mHowAllocated; // This might be ALLOC_SIMPLE or ALLOC_NONE if backed-up variable was at the lowest layer of the call stack.
 1230     mAttrib = aVarBkp.mAttrib;
 1231     mType = aVarBkp.mType;
 1232 }
 1233 
 1234 
 1235 
 1236 void Var::FreeAndRestoreFunctionVars(Func &aFunc, VarBkp *&aVarBackup, int &aVarBackupCount)
 1237 {
 1238     int i;
 1239     for (i = 0; i < aFunc.mVarCount; ++i)
 1240         aFunc.mVar[i]->Free(VAR_ALWAYS_FREE_BUT_EXCLUDE_STATIC, true); // Pass "true" to exclude aliases, since their targets should not be freed (they don't belong to this function). Also resets the "uninitialized" attribute.
 1241     for (i = 0; i < aFunc.mLazyVarCount; ++i)
 1242         aFunc.mLazyVar[i]->Free(VAR_ALWAYS_FREE_BUT_EXCLUDE_STATIC, true);
 1243 
 1244     // The freeing (above) MUST be done prior to the restore-from-backup below (otherwise there would be
 1245     // a memory leak).  Static variables are never backed up and thus do not exist in the aVarBackup array.
 1246     // This is because by definition, the contents of statics are not freed or altered by the calling procedure
 1247     // (regardless how recursive or multi-threaded the function is).
 1248     if (aVarBackup) // This is the indicator that a backup was made; thus a restore is also needed.
 1249     {
 1250         for (i = 0; i < aVarBackupCount; ++i) // Static variables were never backed up so they won't be in this array. See comments above.
 1251         {
 1252             VarBkp &bkp = aVarBackup[i];
 1253             bkp.mVar->Restore(bkp);
 1254         }
 1255         free(aVarBackup);
 1256         aVarBackup = NULL; // Some callers want this reset; it's an indicator of whether the next function call in this expression (if any) will have a backup.
 1257     }
 1258 }
 1259 
 1260 
 1261 
 1262 // Used by the debugger.
 1263 void VarBkp::ToToken(ExprTokenType &aValue)
 1264 {
 1265     switch (mAttrib & (VAR_ATTRIB_HAS_VALID_INT64 | VAR_ATTRIB_HAS_VALID_DOUBLE | VAR_ATTRIB_OBJECT))
 1266     {
 1267     case VAR_ATTRIB_OBJECT: aValue.SetValue(mObject); break;
 1268     case VAR_ATTRIB_HAS_VALID_INT64: aValue.SetValue(mContentsInt64); break;
 1269     case VAR_ATTRIB_HAS_VALID_DOUBLE: aValue.SetValue(mContentsDouble); break;
 1270     default:
 1271         aValue.SetValue(mCharContents);
 1272         if (mAttrib & VAR_ATTRIB_UNINITIALIZED)
 1273             aValue.symbol = SYM_MISSING;
 1274     }
 1275 }
 1276 
 1277 
 1278 
 1279 ResultType Var::ValidateName(LPCTSTR aName, int aDisplayError)
 1280 // Returns OK or FAIL.
 1281 {
 1282     if (!*aName) return FAIL;
 1283     // Seems best to disallow variables that start with numbers so that more advanced
 1284     // parsing (e.g. expressions) can be more easily added in the future.  UPDATE: For
 1285     // backward compatibility with AutoIt2's technique of storing command line args in
 1286     // a numerically-named var (e.g. %1% is the first arg), decided not to do this:
 1287     //if (*aName >= '0' && *aName <= '9')
 1288     //  return g_script.ScriptError("This variable name starts with a number, which is not allowed.", aName);
 1289     TCHAR c;
 1290     LPCTSTR cp;
 1291     for (cp = aName; *cp; ++cp)
 1292     {
 1293         // ispunct(): @ # $ _ [ ] ? ! % & " ' ( ) * + - ^ . / \ : ; , < = > ` ~ | { }
 1294         // Of the above, it seems best to disallow the following:
 1295         // () reserved: user-defined functions, e.g. var = myfunc2(myfunc1() + 2)
 1296         // ! reserved: "not"
 1297         // % reserved: deref char
 1298         // & reserved: "and" or "bitwise and"
 1299         // ' seems too iffy
 1300         // " seems too iffy
 1301         // */-+ reserved: math
 1302         // , reserved: delimiter
 1303         // . reserved: objects
 1304         // : reserved: ternary
 1305         // ? reserved: ternary
 1306         // ; reserved: comment
 1307         // \ seems too iffy
 1308         // <=> reserved: comparison
 1309         // ^ reserved: "bitwise xor"
 1310         // ` reserved: escape char
 1311         // {} reserved: blocks
 1312         // | reserved: "or" or "bitwise or"
 1313         // ~ reserved: "bitwise not"
 1314         // [] reserved: array/object indexing
 1315 
 1316         // Rewritten for v1.0.36.02 to enhance performance and also forbid characters such as linefeed and
 1317         // alert/bell inside variable names.  Ordered to maximize short-circuit performance for the most-often
 1318         // used characters in variables names:
 1319         c = *cp;  // For performance.
 1320         if (!cisalnum(c) // It's not a core/legacy alphanumeric.
 1321             && !(c & ~0x7F) // It's not an extended ASCII character such as €/¶/¿ (for simplicity and backward compatibility, these are always allowed).
 1322             && !_tcschr(_T("_$#@"), c)) // It's not a permitted punctuation mark.  L31: Removed [], now reserved for array/object indexing. Also removed ? while I was at it.
 1323         {
 1324             if (aDisplayError)
 1325             {
 1326                 TCHAR msg[512];
 1327                 sntprintf(msg, _countof(msg), _T("The following %s name contains an illegal character:\n\"%-1.300s\"")
 1328                     , aDisplayError == DISPLAY_VAR_ERROR ? _T("variable") : _T("function")
 1329                     , aName);
 1330                 return g_script.ScriptError(msg);
 1331             }
 1332             else
 1333                 return FAIL;
 1334         }
 1335     }
 1336     // Otherwise:
 1337     return OK;
 1338 }
 1339 
 1340 ResultType Var::AssignStringFromCodePage(LPCSTR aBuf, int aLength, UINT aCodePage)
 1341 {
 1342 #ifndef UNICODE
 1343     // Not done since some callers have a more effective optimization in place:
 1344     //if (aCodePage == CP_ACP || aCodePage == GetACP())
 1345         // Avoid unnecessary conversion (ACP -> UTF16 -> ACP).
 1346         //return AssignString(aBuf, aLength, true, false);
 1347     // Convert from specified codepage to UTF-16,
 1348     CStringWCharFromChar wide_buf(aBuf, aLength, aCodePage);
 1349     // then back to the active codepage:
 1350     return AssignStringToCodePage(wide_buf, wide_buf.GetLength(), CP_ACP);
 1351 #else
 1352     int iLen = MultiByteToWideChar(aCodePage, 0, aBuf, aLength, NULL, 0);
 1353     if (iLen > 0) {
 1354         if (!AssignString(NULL, iLen, true, false))
 1355             return FAIL;
 1356         LPWSTR aContents = Contents(TRUE, TRUE);
 1357         iLen = MultiByteToWideChar(aCodePage, 0, aBuf, aLength, (LPWSTR) aContents, iLen);
 1358         aContents[iLen] = 0;
 1359         if (!iLen)
 1360             return FAIL;
 1361         SetCharLength(aContents[iLen - 1] ? iLen : iLen - 1);
 1362     }
 1363     else
 1364         Assign(); // Return value is ambiguous in this case: may be zero-length input or an error.  For simplicity, return OK.
 1365     return OK;
 1366 #endif
 1367 }
 1368 
 1369 ResultType Var::AssignStringToCodePage(LPCWSTR aBuf, int aLength, UINT aCodePage, DWORD aFlags, char aDefChar)
 1370 {
 1371     char *pDefChar;
 1372     if (aCodePage == CP_UTF8 || aCodePage == CP_UTF7) {
 1373         pDefChar = NULL;
 1374         aFlags = 0;
 1375     }
 1376     else
 1377         pDefChar = &aDefChar;
 1378     int iLen = WideCharToMultiByte(aCodePage, aFlags, aBuf, aLength, NULL, 0, pDefChar, NULL);
 1379     if (iLen > 0) {
 1380         if (!SetCapacity(iLen, true, false))
 1381             return FAIL;
 1382         LPSTR aContents = (LPSTR) Contents(TRUE, TRUE);
 1383         iLen = WideCharToMultiByte(aCodePage, aFlags, aBuf, aLength, aContents, iLen, pDefChar, NULL);
 1384         aContents[iLen] = 0;
 1385         if (!iLen)
 1386             return FAIL;
 1387 #ifndef UNICODE
 1388         SetCharLength(aContents[iLen - 1] ? iLen : iLen - 1);
 1389 #endif
 1390     }
 1391     else
 1392         Assign();
 1393     return OK;
 1394 }
 1395 
 1396 __forceinline void Var::MaybeWarnUninitialized()
 1397 {
 1398     if (IsUninitializedNormalVar())
 1399     {
 1400         // The following should not be possible; if it is, there's a bug and we want to know about it:
 1401         //if (mByteLength != 0)
 1402         //  MarkInitialized();  // "self-correct" if we catch a var that has normal content but wasn't marked initialized
 1403         //else
 1404             g_script.WarnUninitializedVar(this);
 1405     }
 1406 }