home *** CD-ROM | disk | FTP | other *** search
/ Computer Shopper 242 / Issue 242 - April 2008 - DPCS0408DVD.ISO / Open Source / AutoHotKey / Source / AutoHotkey104705_source.exe / source / var.cpp < prev    next >
Encoding:
C/C++ Source or Header  |  2007-11-16  |  59.9 KB  |  1,101 lines

  1. /*
  2. AutoHotkey
  3.  
  4. Copyright 2003-2007 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. char Var::sEmptyString[] = ""; // For explanation, see its declaration in .h file.
  24.  
  25.  
  26. ResultType Var::AssignHWND(HWND aWnd)
  27. {
  28.     // Convert to unsigned 64-bit to support for 64-bit pointers.  Since most script operations --
  29.     // such as addition and comparison -- read strings in as signed 64-bit, it is documented that
  30.     // math and other numerical operations should never be performed on these while they exist
  31.     // as strings in script variables:
  32.     //#define ASSIGN_HWND_TO_VAR(var, hwnd) var->Assign((unsigned __int64)hwnd)
  33.     // UPDATE: Always assign as hex for better compatibility with Spy++ and other apps that
  34.     // report window handles:
  35.     char buf[64];
  36.     *buf = '0';
  37.     buf[1] = 'x';
  38.     _ui64toa((unsigned __int64)aWnd, buf + 2, 16);
  39.     return Assign(buf);
  40. }
  41.  
  42.  
  43.  
  44. ResultType Var::Assign(DWORD aValueToAssign) // For some reason, this function is actually faster when not inline.
  45. // Returns OK or FAIL.
  46. {
  47.     char value_string[256];
  48.     return Assign(UTOA(aValueToAssign, value_string));
  49. }
  50.  
  51.  
  52.  
  53. ResultType Var::Assign(int aValueToAssign) // For some reason, this function is actually faster when not inline.
  54. {
  55.     char value_string[256];
  56.     // ITOA() seems to perform quite a bit better than sprintf() in this case:
  57.     return Assign(ITOA(aValueToAssign, value_string));
  58.     //snprintf(value_string, sizeof(value_string), "%d", aValueToAssign);
  59.     //return Assign(value_string);
  60. }
  61.  
  62.  
  63.  
  64. ResultType Var::Assign(__int64 aValueToAssign) // For some reason, this function is actually faster when not inline.
  65. // Returns OK or FAIL.
  66. {
  67.     char value_string[256];
  68.     return Assign(ITOA64(aValueToAssign, value_string));
  69. }
  70.  
  71.  
  72. // Currently not needed:
  73. //ResultType Var::Assign(unsigned __int64 aValueToAssign)
  74. //// Since most script features that "read in" a number from a string (such as addition and comparison)
  75. //// read the strings as signed values, this function here should only be used when it is documented
  76. //// that math and comparisons should not be performed on such values.
  77. //// Returns OK or FAIL.
  78. //{
  79. //    char value_string[256];
  80. //    UTOA64(aValueToAssign, value_string);
  81. //    return Assign(value_string);
  82. //}
  83.  
  84.  
  85.  
  86. ResultType Var::Assign(double aValueToAssign)
  87. // It's best to call this method -- rather than manually converting to double -- so that the
  88. // digits/formatting/precision is consistent throughout the program.
  89. // Returns OK or FAIL.
  90. {
  91.     char value_string[MAX_FORMATTED_NUMBER_LENGTH + 1];
  92.     return Assign(value_string
  93.         , snprintf(value_string, sizeof(value_string), g.FormatFloat, aValueToAssign)); // "%0.6f"; %f can handle doubles in MSVC++.);
  94. }
  95.  
  96.  
  97.  
  98. ResultType Var::Assign(ExprTokenType &aToken)
  99. // Returns OK or FAIL.
  100. // Writes aToken's value into aOutputVar based on the type of the token.
  101. // Caller must ensure that aToken.symbol is an operand (not an operator or other symbol).
  102. // Caller must ensure that if aToken.symbol==SYM_VAR, aToken.var->Type()==VAR_NORMAL, not the clipboard or
  103. // any built-in var.  However, this->Type() can be VAR_CLIPBOARD.
  104. {
  105.     switch (aToken.symbol)
  106.     {
  107.     case SYM_INTEGER: return Assign(aToken.value_int64); // Listed first for performance because it's Likely the most common from our callers.
  108.     case SYM_VAR:
  109.     {
  110.         // Below: Caller has ensured that aToken.var's Type() is always VAR_NORMAL.
  111.         // Below also relies on the fact that aliases can't point to other aliases (enforced by UpdateAlias()).
  112.         Var &source_var = *(aToken.var->mType == VAR_ALIAS ? aToken.var->mAliasFor : aToken.var);
  113.         return (source_var.mAttrib & VAR_ATTRIB_BINARY_CLIP) // Caller has ensured that source_var's Type() is VAR_NORMAL.
  114.             ? AssignBinaryClip(source_var) // Caller wants a variable with binary contents assigned (copied) to another variable (usually VAR_CLIPBOARD).
  115.             : Assign(source_var.mContents, source_var.mLength); // Pass length to improve performance.
  116.     }
  117.     case SYM_FLOAT:   return Assign(aToken.value_double); // Listed last because it's probably the least common.
  118.     default:          return Assign(aToken.marker); // SYM_STRING or SYM_OPERAND.
  119.     }
  120. }
  121.  
  122.  
  123.  
  124. ResultType Var::AssignClipboardAll()
  125. // Caller must ensure that "this" is a normal variable or the clipboard (though if it's the clipboard, this
  126. // function does nothing).
  127. {
  128.     if (mType == VAR_ALIAS)
  129.         // For maintainability, it seems best not to use the following method:
  130.         //    Var &var = *(mType == VAR_ALIAS ? mAliasFor : this);
  131.         // If that were done, bugs would be easy to introduce in a long function like this one
  132.         // if your forget at use the implicit "this" by accident.  So instead, just call self.
  133.         return mAliasFor->AssignClipboardAll();
  134.     if (mType == VAR_CLIPBOARD) // Seems pointless to do Clipboard:=ClipboardAll, and the below isn't equipped
  135.         return OK;              // to handle it, so make this have no effect.
  136.     if (!g_clip.Open())
  137.         return g_script.ScriptError(CANT_OPEN_CLIPBOARD_READ);
  138.  
  139.     // Calculate the size needed:
  140.     // EnumClipboardFormats() retrieves all formats, including synthesized formats that don't
  141.     // actually exist on the clipboard but are instead constructed on demand.  Unfortunately,
  142.     // there doesn't appear to be any way to reliably determine which formats are real and
  143.     // which are synthesized (if there were such a way, a large memory savings could be
  144.     // realized by omitting the synthesized formats from the saved version). One thing that
  145.     // is certain is that the "real" format(s) come first and the synthesized ones afterward.
  146.     // However, that's not quite enough because although it is recommended that apps store
  147.     // the primary/preferred format first, the OS does not enforce this.  For example, testing
  148.     // shows that the apps do not have to store CF_UNICODETEXT prior to storing CF_TEXT,
  149.     // in which case the clipboard might have inaccurate CF_TEXT as the first element and
  150.     // more accurate/complete (non-synthesized) CF_UNICODETEXT stored as the next.
  151.     // In spite of the above, the below seems likely to be accurate 99% or more of the time,
  152.     // which seems worth it given the large savings of memory that are achieved, especially
  153.     // for large quantities of text or large images. Confidence is further raised by the
  154.     // fact that MSDN says there's no advantage/reason for an app to place multiple formats
  155.     // onto the clipboard if those formats are available through synthesis.
  156.     // And since CF_TEXT always(?) yields synthetic CF_OEMTEXT and CF_UNICODETEXT, and
  157.     // probably (but less certainly) vice versa: if CF_TEXT is listed first, it might certainly
  158.     // mean that the other two do not need to be stored.  There is some slight doubt about this
  159.     // in a situation where an app explicitly put CF_TEXT onto the clipboard and then followed
  160.     // it with CF_UNICODETEXT that isn't synthesized, nor does it match what would have been
  161.     // synthesized. However, that seems extremely unlikely (it would be much more likely for
  162.     // an app to store CF_UNICODETEXT *first* followed by custom/non-synthesized CF_TEXT, but
  163.     // even that might be unheard of in practice).  So for now -- since there is no documentation
  164.     // to be found about this anywhere -- it seems best to omit some of the most common
  165.     // synthesized formats:
  166.     // CF_TEXT is the first of three text formats to appear: Omit CF_OEMTEXT and CF_UNICODETEXT.
  167.     //    (but not vice versa since those are less certain to be synthesized)
  168.     //    (above avoids using four times the amount of memory that would otherwise be required)
  169.     //    UPDATE: Only the first text format is included now, since MSDN says there is no
  170.     //    advantage/reason to having multiple non-synthesized text formats on the clipboard.
  171.     // CF_DIB: Always omit this if CF_DIBV5 is available (which must be present on Win2k+, at least
  172.     // as a synthesized format, whenever CF_DIB is present?) This policy seems likely to avoid
  173.     // the issue where CF_DIB occurs first yet CF_DIBV5 that comes later is *not* synthesized,
  174.     // perhaps simply because the app stored DIB prior to DIBV5 by mistake (though there is
  175.     // nothing mandatory, so maybe it's not really a mistake). Note: CF_DIBV5 supports alpha
  176.     // channel / transparency, and perhaps other things, and it is likely that when synthesized,
  177.     // no information of the original CF_DIB is lost. Thus, when CF_DIBV5 is placed back onto
  178.     // the clipboard, any app that needs CF_DIB will have it synthesized back to the original
  179.     // data (hopefully). It's debatable whether to do it that way or store whichever comes first
  180.     // under the theory that an app would never store both formats on the clipboard since MSDN
  181.     // says: "If the system provides an automatic type conversion for a particular clipboard format,
  182.     // there is no advantage to placing the conversion format(s) on the clipboard."
  183.     bool format_is_text;
  184.     HGLOBAL hglobal;
  185.     SIZE_T size;
  186.     UINT format;
  187.     VarSizeType space_needed;
  188.     UINT dib_format_to_omit = 0, meta_format_to_omit = 0, text_format_to_include = 0;
  189.     // Start space_needed off at 4 to allow room for guaranteed final termination of the variable's contents.
  190.     // The termination must be of the same size as format because a single-byte terminator would
  191.     // be read in as a format of 0x00?????? where ?????? is an access violation beyond the buffer.
  192.     for (space_needed = sizeof(format), format = 0; format = EnumClipboardFormats(format);)
  193.     {
  194.         // No point in calling GetLastError() since it would never be executed because the loop's
  195.         // condition breaks on zero return value.
  196.         format_is_text = (format == CF_TEXT || format == CF_OEMTEXT || format == CF_UNICODETEXT);
  197.         if ((format_is_text && text_format_to_include) // The first text format has already been found and included, so exclude all other text formats.
  198.             || format == dib_format_to_omit) // ... or this format was marked excluded by a prior iteration.
  199.             continue;
  200.         // GetClipboardData() causes Task Manager to report a (sometimes large) increase in
  201.         // memory utilization for the script, which is odd since it persists even after the
  202.         // clipboard is closed.  However, when something new is put onto the clipboard by the
  203.         // the user or any app, that memory seems to get freed automatically.  Also, 
  204.         // GetClipboardData(49356) fails in MS Visual C++ when the copied text is greater than
  205.         // about 200 KB (but GetLastError() returns ERROR_SUCCESS).  When pasting large sections
  206.         // of colorized text into MS Word, it can't get the colorized text either (just the plain
  207.         // text). Because of this example, it seems likely it can fail in other places or under
  208.         // other circumstances, perhaps by design of the app. Therefore, be tolerant of failures
  209.         // because partially saving the clipboard seems much better than aborting the operation.
  210.         if (hglobal = g_clip.GetClipboardDataTimeout(format))
  211.         {
  212.             space_needed += (VarSizeType)(sizeof(format) + sizeof(size) + GlobalSize(hglobal)); // The total amount of storage space required for this item.
  213.             if (format_is_text) // If this is true, then text_format_to_include must be 0 since above didn't "continue".
  214.                 text_format_to_include = format;
  215.             if (!dib_format_to_omit)
  216.             {
  217.                 if (format == CF_DIB)
  218.                     dib_format_to_omit = CF_DIBV5;
  219.                 else if (format == CF_DIBV5)
  220.                     dib_format_to_omit = CF_DIB;
  221.             }
  222.             if (!meta_format_to_omit) // Checked for the same reasons as dib_format_to_omit.
  223.             {
  224.                 if (format == CF_ENHMETAFILE)
  225.                     meta_format_to_omit = CF_METAFILEPICT;
  226.                 else if (format == CF_METAFILEPICT)
  227.                     meta_format_to_omit = CF_ENHMETAFILE;
  228.             }
  229.         }
  230.         //else omit this format from consideration.
  231.     }
  232.  
  233.     if (space_needed == sizeof(format)) // This works because even a single empty format requires space beyond sizeof(format) for storing its format+size.
  234.     {
  235.         g_clip.Close();
  236.         return Assign(); // Nothing on the clipboard, so just make the variable blank.
  237.     }
  238.  
  239.     // Resize the output variable, if needed:
  240.     if (!Assign(NULL, space_needed - 1, true, false))
  241.     {
  242.         g_clip.Close();
  243.         return FAIL; // Above should have already reported the error.
  244.     }
  245.  
  246.     // Retrieve and store all the clipboard formats.  Because failures of GetClipboardData() are now
  247.     // tolerated, it seems safest to recalculate the actual size (actual_space_needed) of the data
  248.     // in case it varies from that found in the estimation phase.  This is especially necessary in
  249.     // case GlobalLock() ever fails, since that isn't even attempted during the estimation phase.
  250.     // Otherwise, the variable's mLength member would be set to something too high (the estimate),
  251.     // which might cause problems elsewhere.
  252.     LPVOID hglobal_locked;
  253.     LPVOID binary_contents = mContents;
  254.     VarSizeType added_size, actual_space_used;
  255.     for (actual_space_used = sizeof(format), format = 0; format = EnumClipboardFormats(format);)
  256.     {
  257.         // No point in calling GetLastError() since it would never be executed because the loop's
  258.         // condition breaks on zero return value.
  259.         if ((format == CF_TEXT || format == CF_OEMTEXT || format == CF_UNICODETEXT) && format != text_format_to_include
  260.             || format == dib_format_to_omit || format == meta_format_to_omit)
  261.             continue;
  262.         // Although the GlobalSize() documentation implies that a valid HGLOBAL should not be zero in
  263.         // size, it does happen, at least in MS Word and for CF_BITMAP.  Therefore, in order to save
  264.         // the clipboard as accurately as possible, also save formats whose size is zero.  Note that
  265.         // GlobalLock() fails to work on hglobals of size zero, so don't do it for them.
  266.         if ((hglobal = g_clip.GetClipboardDataTimeout(format)) // This and the next line rely on short-circuit boolean order.
  267.             && (!(size = GlobalSize(hglobal)) || (hglobal_locked = GlobalLock(hglobal)))) // Size of zero or lock succeeded: Include this format.
  268.         {
  269.             // Any changes made to how things are stored here should also be made to the size-estimation
  270.             // phase so that space_needed matches what is done here:
  271.             added_size = (VarSizeType)(sizeof(format) + sizeof(size) + size);
  272.             actual_space_used += added_size;
  273.             if (actual_space_used > mCapacity) // Tolerate incorrect estimate by omitting formats that won't fit. Note that mCapacity is the granted capacity, which might be a little larger than requested.
  274.                 actual_space_used -= added_size;
  275.             else
  276.             {
  277.                 *(UINT *)binary_contents = format;
  278.                 binary_contents = (char *)binary_contents + sizeof(format);
  279.                 *(SIZE_T *)binary_contents = size;
  280.                 binary_contents = (char *)binary_contents + sizeof(size);
  281.                 if (size)
  282.                 {
  283.                     memcpy(binary_contents, hglobal_locked, size);
  284.                     binary_contents = (char *)binary_contents + size;
  285.                 }
  286.                 //else hglobal_locked is not valid, so don't reference it or unlock it.
  287.             }
  288.             if (size)
  289.                 GlobalUnlock(hglobal); // hglobal not hglobal_locked.
  290.         }
  291.     }
  292.     g_clip.Close();
  293.     *(UINT *)binary_contents = 0; // Final termination (must be UINT, see above).
  294.     mLength = actual_space_used - 1; // Omit the final zero-byte from the length in case any other routines assume that exactly one zero exists at the end of var's length.
  295.     mAttrib |= VAR_ATTRIB_BINARY_CLIP;
  296.     return OK;
  297. }
  298.  
  299.  
  300.  
  301. ResultType Var::AssignBinaryClip(Var &aSourceVar)
  302. // Caller must ensure that this->Type() is VAR_NORMAL or VAR_CLIPBOARD (usually via load-time validation).
  303. // Caller must ensure that aSourceVar->Type()==VAR_NORMAL and aSourceVar->IsBinaryClip()==true.
  304. {
  305.     if (mType == VAR_ALIAS)
  306.         // For maintainability, it seems best not to use the following method:
  307.         //    Var &var = *(mType == VAR_ALIAS ? mAliasFor : this);
  308.         // If that were done, bugs would be easy to introduce in a long function like this one
  309.         // if your forget at use the implicit "this" by accident.  So instead, just call self.
  310.         return mAliasFor->AssignBinaryClip(aSourceVar);
  311.  
  312.     // Resolve early for maintainability.
  313.     // Relies on the fact that aliases can't point to other aliases (enforced by UpdateAlias()).
  314.     Var &source_var = (aSourceVar.mType == VAR_ALIAS) ? *aSourceVar.mAliasFor : aSourceVar;
  315.  
  316.     if (mType == VAR_NORMAL) // Copy a binary variable to another variable that isn't the clipboard.
  317.     {
  318.         if (source_var.mContents == mContents) // v1.0.45: source==dest, so nothing to do. It's compared this way in case aSourceVar is a ByRef/alias. This covers even that situation.
  319.             return OK;
  320.         if (!Assign(NULL, source_var.mLength))
  321.             return FAIL; // Above should have already reported the error.
  322.         memcpy(mContents, source_var.mContents, source_var.mLength + 1); // Add 1 not sizeof(format). Note that mContents might have just changed due Assign() above.
  323.         mAttrib |= VAR_ATTRIB_BINARY_CLIP;
  324.         return OK; // No need to call Close() in this case.
  325.     }
  326.  
  327.     // SINCE ABOVE DIDN'T RETURN, A VARIABLE CONTAINING BINARY CLIPBOARD DATA IS BEING COPIED BACK ONTO THE CLIPBOARD.
  328.     if (!g_clip.Open())
  329.         return g_script.ScriptError(CANT_OPEN_CLIPBOARD_WRITE);
  330.     EmptyClipboard(); // Failure is not checked for since it's probably impossible under these conditions.
  331.  
  332.     // In case the variable contents are incomplete or corrupted (such as having been read in from a
  333.     // bad file with FileRead), prevent reading beyond the end of the variable:
  334.     LPVOID next, binary_contents = source_var.mContents; // Fix for v1.0.47.05: Changed aSourceVar to source_var in this line and the next.
  335.     LPVOID binary_contents_max = (char *)binary_contents + source_var.mLength + 1; // The last acessible byte, which should be the last byte of the (UINT)0 terminator.
  336.     HGLOBAL hglobal;
  337.     LPVOID hglobal_locked;
  338.     UINT format;
  339.     SIZE_T size;
  340.  
  341.     while ((next = (char *)binary_contents + sizeof(format)) <= binary_contents_max
  342.         && (format = *(UINT *)binary_contents)) // Get the format.  Relies on short-circuit boolean order.
  343.     {
  344.         binary_contents = next;
  345.         if ((next = (char *)binary_contents + sizeof(size)) > binary_contents_max)
  346.             break;
  347.         size = *(UINT *)binary_contents; // Get the size of this format's data.
  348.         binary_contents = next;
  349.         if ((next = (char *)binary_contents + size) > binary_contents_max)
  350.             break;
  351.         if (   !(hglobal = GlobalAlloc(GMEM_MOVEABLE, size))   ) // size==0 is okay.
  352.         {
  353.             g_clip.Close();
  354.             return g_script.ScriptError(ERR_OUTOFMEM); // Short msg since so rare.
  355.         }
  356.         if (size) // i.e. Don't try to lock memory of size zero.  It won't work and it's not needed.
  357.         {
  358.             if (   !(hglobal_locked = GlobalLock(hglobal))   )
  359.             {
  360.                 GlobalFree(hglobal);
  361.                 g_clip.Close();
  362.                 return g_script.ScriptError("GlobalLock"); // Short msg since so rare.
  363.             }
  364.             memcpy(hglobal_locked, binary_contents, size);
  365.             GlobalUnlock(hglobal);
  366.             binary_contents = next;
  367.         }
  368.         //else hglobal is just an empty format, but store it for completeness/accuracy (e.g. CF_BITMAP).
  369.         SetClipboardData(format, hglobal); // The system now owns hglobal.
  370.     }
  371.     return g_clip.Close();
  372. }
  373.  
  374.  
  375.  
  376. ResultType Var::Assign(char *aBuf, VarSizeType aLength, bool aExactSize, bool aObeyMaxMem)
  377. // Returns OK or FAIL.
  378. // If aBuf isn't NULL, caller must ensure that aLength is either VARSIZE_MAX (which tells us that the
  379. // entire strlen() of aBuf should be used) or an explicit length (can be zero) that the caller must
  380. // ensure is less than or equal to the total length of aBuf (if less, only a substring is copied).
  381. // If aBuf is NULL, the variable will be set up to handle a string of at least aLength
  382. // in length.  In addition, if the var is the clipboard, it will be prepared for writing.
  383. // Any existing contents of this variable will be destroyed regardless of whether aBuf is NULL.
  384. // Note that aBuf's memory can safely overlap with that of this->Contents() because in that case the
  385. // new length of the contents will always be less than or equal to the old length, and thus no
  386. // reallocation/expanion is needed (such an expansion would free the source before it could be
  387. // written to the destination).  This is because callers pass in an aBuf that is either:
  388. // 1) Between this->Contents() and its terminator.
  389. // 2) Equal to this->Contents() but with aLength passed in as shorter than this->Length().
  390. //
  391. // Caller can omit both params to set a var to be empty-string, but in that case, if the variable
  392. // is of large capacity, its memory will not be freed.  This is by design because it allows the
  393. // caller to exploit its knowledge of whether the var's large capacity is likely to be needed
  394. // again in the near future, thus reducing the expected amount of memory fragmentation.
  395. // To explicitly free the memory, use Assign("").
  396. {
  397.     if (mType == VAR_ALIAS)
  398.         // For maintainability, it seems best not to use the following method:
  399.         //    Var &var = *(mType == VAR_ALIAS ? mAliasFor : this);
  400.         // If that were done, bugs would be easy to introduce in a long function like this one
  401.         // if your forget at use the implicit "this" by accident.  So instead, just call self.
  402.         return mAliasFor->Assign(aBuf, aLength, aExactSize);
  403.  
  404.     bool do_assign = true;        // Set defaults.
  405.     bool free_it_if_large = true; //
  406.     if (!aBuf)
  407.         if (aLength == VARSIZE_MAX) // Caller omitted this param too, so it wants to assign empty string.
  408.         {
  409.             free_it_if_large = false;
  410.             aLength = 0; // aBuf is set to "" further below.
  411.         }
  412.         else // Caller gave a NULL buffer to signal us to ensure the var is at least aLength in capacity.
  413.             do_assign = false;
  414.     else // Caller provided a non-NULL buffer.
  415.         if (aLength == VARSIZE_MAX) // Caller wants us to determine its length.
  416.             aLength = (mContents == aBuf) ? mLength : (VarSizeType)strlen(aBuf); // v1.0.45: Added optimization check: (mContents == aBuf).
  417.         //else leave aLength as the caller-specified value in case it's explicitly shorter than the apparent length.
  418.     if (!aBuf)
  419.         aBuf = "";  // 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).
  420.  
  421.     size_t space_needed = aLength + 1; // +1 for the zero terminator.
  422.  
  423.     if (mType == VAR_CLIPBOARD)
  424.     {
  425.         if (do_assign)
  426.             // Just return the result of this.  Note: The clipboard var's attributes,
  427.             // such as mLength, are not maintained because it's a variable whose
  428.             // contents usually aren't under our control.  UPDATE: aTrimIt isn't
  429.             // needed because the clipboard is never assigned something that needs
  430.             // to be trimmed in this way (i.e. PerformAssign handles the trimming
  431.             // on its own for the clipboard, due to the fact that dereferencing
  432.             // into the temp buf is unnecessary when the clipboard is the target):
  433.             return g_clip.Set(aBuf, aLength); //, aTrimIt);
  434.         else
  435.             // We open it for write now, because some caller's don't call
  436.             // this function to write to the contents of the var, they
  437.             // do it themselves.  Note: Below call will have displayed
  438.             // any error that occurred:
  439.             return g_clip.PrepareForWrite(space_needed) ? OK : FAIL;
  440.     }
  441.  
  442.     // Since above didn't return, this variable isn't the clipboard.
  443.     if (space_needed > g_MaxVarCapacity && aObeyMaxMem) // v1.0.43.03: aObeyMaxMem was added since some callers aren't supposed to obey it.
  444.         return g_script.ScriptError(ERR_MEM_LIMIT_REACHED);
  445.  
  446.     if (space_needed < 2) // Variable is being assigned the empty string (or a deref that resolves to it).
  447.     {
  448.         Free(free_it_if_large ? VAR_FREE_IF_LARGE : VAR_NEVER_FREE); // This also makes the variable blank and removes VAR_ATTRIB_BINARY_CLIP.
  449.         return OK;
  450.     }
  451.  
  452.     // The below is done regardless of whether the section that follows it fails and returns early because
  453.     // it's the correct thing to do in all cases.
  454.     // For simplicity, this is done unconditionally even though it should be needed only
  455.     // when do_assign is true. It's the caller's responsibility to turn on the binary-clip
  456.     // attribute (if appropriate) by calling Var::Close() with the right option.
  457.     mAttrib &= ~VAR_ATTRIB_BINARY_CLIP;
  458.     // HOWEVER, other things like making mLength 0 and mContents blank are not done here for performance
  459.     // reasons (it seems too rare that early return/failure will occur below, since it's only due to
  460.     // out-of-memory... and even if it does happen, there a probably no consequences to leaving the variable
  461.     // the way it is now (rather than forcing it to be black) since the script thread that caused the error
  462.     // will be ended.
  463.  
  464.     if (space_needed > mCapacity)
  465.     {
  466.         size_t new_size; // Use a new name, rather than overloaidng space_needed, for maintainability.
  467.         char *new_mem;
  468.  
  469.         switch (mHowAllocated)
  470.         {
  471.         case ALLOC_NONE:
  472.         case ALLOC_SIMPLE:
  473.             if (space_needed <= MAX_ALLOC_SIMPLE)
  474.             {
  475.                 // v1.0.31: Conserve memory within large arrays by allowing elements of length 1 or 7, for such
  476.                 // things as the storage of boolean values, or the storage of short numbers (it's best to use
  477.                 // multiples of 4 for size due to byte alignment in SimpleHeap; e.g. lengths of 3 and 7).
  478.                 // Because the above checked that space_needed > mCapacity, the capacity will increase but
  479.                 // never decrease in this section, which prevent a memory leak by only ever wasting a maximum
  480.                 // of 2+7+MAX_ALLOC_SIMPLE for each variable (and then only in the worst case -- in the average
  481.                 // case, it saves memory by avoiding the overhead incurred for each separate malloc'd block).
  482.                 if (space_needed < 5) // 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.
  483.                     new_size = 4; // v1.0.45: Increased from 2 to 4 to exploit byte alignment in SimpleHeap.
  484.                 else if (aExactSize) // Allows VarSetCapacity() to make more flexible use of SimpleHeap.
  485.                     new_size = space_needed;
  486.                 else
  487.                 {
  488.                     if (space_needed < 9)
  489.                         new_size = 8; // v1.0.45: Increased from 7 to 8 to exploit 32-bit alignment in SimpleHeap.
  490.                     else // space_needed <= MAX_ALLOC_SIMPLE
  491.                         new_size = MAX_ALLOC_SIMPLE;
  492.                 }
  493.                 // In the case of mHowAllocated==ALLOC_SIMPLE, the following will allocate another block
  494.                 // from SimpleHeap even though the var already had one. This is by design because it can
  495.                 // happen only a limited number of times per variable. See comments further above for details.
  496.                 if (   !(new_mem = SimpleHeap::Malloc(new_size))   )
  497.                     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.
  498.                 mHowAllocated = ALLOC_SIMPLE;  // In case it was previously ALLOC_NONE. This step must be done only after the alloc succeeded.
  499.                 break;
  500.             }
  501.             // ** ELSE DON'T BREAK, JUST FALL THROUGH TO THE NEXT CASE. **
  502.             // **
  503.         case ALLOC_MALLOC: // Can also reach here by falling through from above.
  504.             // This case can happen even if space_needed is less than MAX_ALLOC_SIMPLE
  505.             // because once a var becomes ALLOC_MALLOC, it should never change to
  506.             // one of the other alloc modes.  See comments higher above for explanation.
  507.  
  508.             new_size = space_needed; // Below relies on this being initialized unconditionally.
  509.             if (!aExactSize)
  510.             {
  511.                 // Allow a little room for future expansion to cut down on the number of
  512.                 // free's and malloc's we expect to have to do in the future for this var:
  513.                 if (new_size < 16) // v1.0.45.03: Added this new size to prevent all local variables in a recursive
  514.                     new_size = 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.
  515.                 else if (new_size < MAX_PATH)
  516.                     new_size = MAX_PATH;  // An amount that will fit all standard filenames seems good.
  517.                 else if (new_size < (160 * 1024)) // MAX_PATH to 160 KB or less -> 10% extra.
  518.                     new_size = (size_t)(new_size * 1.1);
  519.                 else if (new_size < (1600 * 1024))  // 160 to 1600 KB -> 16 KB extra
  520.                     new_size += (16 * 1024);
  521.                 else if (new_size < (6400 * 1024)) // 1600 to 6400 KB -> 1% extra
  522.                     new_size = (size_t)(new_size * 1.01);
  523.                 else  // 6400 KB or more: Cap the extra margin at some reasonable compromise of speed vs. mem usage: 64 KB
  524.                     new_size += (64 * 1024);
  525.                 if (new_size > g_MaxVarCapacity && aObeyMaxMem) // v1.0.43.03: aObeyMaxMem was added since some callers aren't supposed to obey it.
  526.                     new_size = g_MaxVarCapacity;  // which has already been verified to be enough.
  527.             }
  528.             //else space_needed was already verified higher above to be within bounds.
  529.  
  530.             // In case the old memory area is large, free it before allocating the new one.  This reduces
  531.             // the peak memory load on the system and reduces the chance of an actual out-of-memory error.
  532.             bool memory_was_freed;
  533.             if (memory_was_freed = (mHowAllocated == ALLOC_MALLOC && mCapacity)) // 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.
  534.                 free(mContents); // The other members are left temporarily out-of-sync for performance (they're resync'd only if an error occurs).
  535.             //else mContents contains a "" or it points to memory on SimpleHeap, so don't attempt to free it.
  536.  
  537.             if (   new_size > 2147483647 || !(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.
  538.             {
  539.                 if (memory_was_freed) // Resync members to reflect the fact that it was freed (it's done this way for performance).
  540.                 {
  541.                     mCapacity = 0;             // Invariant: Anyone setting mCapacity to 0 must also set
  542.                     mContents = sEmptyString;  // mContents to the empty string.
  543.                     mLength = 0;
  544.                 }
  545.                 // IMPORTANT: else it's the empty string (a constant) or it points to memory on SimpleHeap,
  546.                 // so don't change mContents/Capacity (that would cause a memory leak for reasons described elsewhere).
  547.                 // Also, don't bother making the variable blank and its length zero.  Just leave its contents
  548.                 // untouched due to the rarity of out-of-memory and the fact that the script thread will be terminated
  549.                 // anyway, so in most cases won't care what the contents are.
  550.                 return g_script.ScriptError(ERR_OUTOFMEM ERR_ABORT); // ERR_ABORT since an error is most likely to occur at runtime.
  551.             }
  552.  
  553.             // Below is necessary because it might have fallen through from case ALLOC_SIMPLE.
  554.             // This step must be done only after the alloc succeeded (because otherwise, want to keep it
  555.             // set to ALLOC_SIMPLE (fall-through), if that's what it was).
  556.             mHowAllocated = ALLOC_MALLOC;
  557.             break;
  558.         } // switch()
  559.  
  560.         // Since above didn't return, the alloc succeeded.  Because that's true, all the members (except those
  561.         // set in their sections above) are updated together so that they stay consistent with each other:
  562.         mContents = new_mem;
  563.         mCapacity = (VarSizeType)new_size;
  564.     } // if (space_needed > mCapacity)
  565.  
  566.     if (do_assign)
  567.     {
  568.         // Above has ensured that space_needed is either strlen(aBuf)-1 or the length of some
  569.         // substring within aBuf starting at aBuf.  However, aBuf might overlap mContents or
  570.         // even be the same memory address (due to something like GlobalVar := YieldGlobalVar(),
  571.         // in which case ACT_ASSIGNEXPR calls us to assign GlobalVar to GlobalVar).
  572.         if (mContents != aBuf)
  573.         {
  574.             // Don't use strlcpy() or such because:
  575.             // 1) Caller might have specified that only part of aBuf's total length should be copied.
  576.             // 2) mContents and aBuf might overlap (see above comment), in which case strcpy()'s result
  577.             //    is undefined, but memmove() is guaranteed to work (and performs about the same).
  578.             memmove(mContents, aBuf, aLength); // Some callers such as RegEx routines might rely on this copying binary zeroes over rather than stopping at the first binary zero.
  579.         }
  580.         //else nothing needs to be done since source and target are identical.  Some callers probably rely on
  581.         // this optimization.
  582.         mContents[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).
  583.     }
  584.     else // Caller only wanted the variable resized as a preparation for something it will do later.
  585.     {
  586.         // Init for greater robustness/safety (the ongoing conflict between robustness/redundancy and performance).
  587.         // This has been in effect for so long that some callers probably rely on it.
  588.         *mContents = '\0'; // If it's sEmptyVar, that's okay too because it's writable.
  589.         // We've done everything except the actual assignment.  Let the caller handle that.
  590.         // Also, the length will be set below to the expected length in case the caller
  591.         // doesn't override this.
  592.         // Below: Already verified that the length value will fit into VarSizeType.
  593.     }
  594.  
  595.     // Writing to union is safe because above already ensured that "this" isn't an alias.
  596.     mLength = aLength; // aLength was verified accurate higher above.
  597.     return OK;
  598. }
  599.  
  600.  
  601.  
  602. VarSizeType Var::Get(char *aBuf)
  603. // Returns the length of this var's contents.  In addition, if aBuf isn't NULL, it will copy the contents into aBuf.
  604. {
  605.     // For v1.0.25, don't do this because in some cases the existing contents of aBuf will not
  606.     // be altered.  Instead, it will be set to blank as needed further below.
  607.     //if (aBuf) *aBuf = '\0';  // Init early to get it out of the way, in case of early return.
  608.     DWORD result;
  609.     VarSizeType length;
  610.     char 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.
  611.  
  612.     switch(mType)
  613.     {
  614.     case VAR_NORMAL: // Listed first for performance.
  615.         if (!g_NoEnv && !mLength) // If auto-env retrival is on and the var is empty, check to see if it's really an env. var.
  616.         {
  617.             // Regardless of whether aBuf is NULL or not, we don't know at this stage
  618.             // whether mName is the name of a valid environment variable.  Therefore,
  619.             // GetEnvironmentVariable() is currently called once in the case where
  620.             // aBuf is NULL and twice in the case where it's not.  There may be some
  621.             // way to reduce it to one call always, but that is an optimization for
  622.             // the future.  Another reason: Calling it twice seems safer, because we can't
  623.             // be completely sure that it wouldn't act on our (possibly undersized) aBuf
  624.             // buffer even if it doesn't find the env. var.
  625.             // UPDATE: v1.0.36.02: It turns out that GetEnvironmentVariable() is a fairly
  626.             // high overhead call. To improve the speed of accessing blank variables that
  627.             // aren't environment variables (and most aren't), cached_empty_var is used
  628.             // to indicate that the previous size-estimation call to us yielded "no such
  629.             // environment variable" so that the upcoming get-contents call to us can avoid
  630.             // calling GetEnvironmentVariable() again.  Testing shows that this doubles
  631.             // the speed of a simple loop that accesses an empty variable such as the following:
  632.             // SetBatchLines -1
  633.             // Loop 500000
  634.             //    if Var = Test
  635.             //    ...
  636.             static Var *cached_empty_var = NULL; // Doubles the speed of accessing empty variables that aren't environment variables (i.e. most of them).
  637.             if (!(cached_empty_var == this && aBuf) && (result = GetEnvironmentVariable(mName, buf_temp, 0)))
  638.             {
  639.                 // This env. var exists.
  640.                 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.
  641.                 return aBuf
  642.                     ? 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.
  643.                     : result - 1;  // -1 because GetEnvironmentVariable() returns total size needed when called that way.
  644.             }
  645.             else // No matching env. var. or the cache indicates that GetEnvironmentVariable() need not be called.
  646.             {
  647.                 if (aBuf)
  648.                 {
  649.                     *aBuf = '\0';
  650.                     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.
  651.                 }
  652.                 else // Size estimation phase: Since there is no such env. var., flag it for the upcoming get-contents phase.
  653.                     cached_empty_var = this;
  654.                 return 0;
  655.             }
  656.         }
  657.         // Otherwise (since above didn't return), it's not an environment variable (or it is, but there's
  658.         // a script variable of non-zero length that's eclipsing it).
  659.         if (!aBuf)
  660.             return mLength;
  661.         else // Caller provider buffer, so if mLength is zero, just make aBuf empty now and return early (for performance).
  662.             if (!mLength)
  663.             {
  664.                 *aBuf = '\0';
  665.                 return 0;
  666.             }
  667.             //else continue on below.
  668.         if (aBuf == mContents)
  669.             // When we're called from ExpandArg() that was called from PerformAssign(), PerformAssign()
  670.             // relies on this check to avoid the overhead of copying a variables contents onto itself.
  671.             return mLength;
  672.         else if (mLength < 100000)
  673.         {
  674.             // Copy the var contents into aBuf.  Although a little bit slower than CopyMemory() for large
  675.             // variables (say, over 100K), this loop seems much faster for small ones, which is the typical
  676.             // case.  Also of note is that this code section is the main bottleneck for scripts that manipulate
  677.             // large variables, such as this:
  678.             //start_time = %A_TICKCOUNT%
  679.             //my = 0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789
  680.             //tempvar =
  681.             //loop, 2000
  682.             //    tempvar = %tempvar%%My%
  683.             //elapsed_time = %A_TICKCOUNT%
  684.             //elapsed_time -= %start_time%
  685.             //msgbox, elapsed_time = %elapsed_time%
  686.             //return
  687.             for (char *cp = mContents; *cp; *aBuf++ = *cp++);
  688.             *aBuf = '\0';
  689.         }
  690.         else
  691.         {
  692.             CopyMemory(aBuf, mContents, mLength); // Faster for large vars, but large vars aren't typical.
  693.             aBuf[mLength] = '\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).
  694.         }
  695.         return mLength;
  696.  
  697.     case VAR_ALIAS:
  698.         // For maintainability, it seems best not to use the following method:
  699.         //    Var &var = *(mType == VAR_ALIAS ? mAliasFor : this);
  700.         // If that were done, bugs would be easy to introduce in a long function like this one
  701.         // if your forget at use the implicit "this" by accident.  So instead, just call self.
  702.         return mAliasFor->Get(aBuf);
  703.  
  704.     // Built-in vars with volatile contents:
  705.     case VAR_CLIPBOARD:
  706.     {
  707.         length = (VarSizeType)g_clip.Get(aBuf); // It will also copy into aBuf if it's non-NULL.
  708.         if (length == CLIPBOARD_FAILURE)
  709.         {
  710.             // Above already displayed the error, so just return.
  711.             // If we were called only to determine the size, the
  712.             // next call to g_clip.Get() will not put anything into
  713.             // aBuf (it will either fail again, or it will return
  714.             // a length of zero due to the clipboard not already
  715.             // being open & ready), so there's no danger of future
  716.             // buffer overflows as a result of returning zero here.
  717.             // Also, due to this function's return type, there's
  718.             // no easy way to terminate the current hotkey
  719.             // subroutine (or entire script) due to this error.
  720.             // However, due to the fact that multiple attempts
  721.             // are made to open the clipboard, failure should
  722.             // be extremely rare.  And the user will be notified
  723.             // with a MsgBox anyway, during which the subroutine
  724.             // will be suspended:
  725.             length = 0;
  726.         }
  727.         if (aBuf)
  728.             aBuf[length] = '\0'; // Might not be necessary, but kept in case it ever is.
  729.         return length;
  730.     }
  731.  
  732.     case VAR_CLIPBOARDALL: // There's a slight chance this case is never executed; but even if true, it should be kept for maintainability.
  733.         // This variable is directly handled at a higher level.  As documented, any use of ClipboardAll outside of
  734.         // the supported modes yields an empty string.
  735.         if (aBuf)
  736.             *aBuf = '\0';
  737.         return 0;
  738.  
  739.     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.
  740.         return mBIV(aBuf, mName);
  741.     } // switch(mType)
  742. }
  743.  
  744.  
  745.  
  746. void Var::Free(int aWhenToFree, bool aExcludeAliases)
  747. // The name "Free" is a little misleading because this function:
  748. // ALWAYS sets the variable to be blank (except for static variables and aExcludeAliases==true).
  749. // BUT ONLY SOMETIMES frees the memory, depending on various factors described further below.
  750. // Caller must be aware that ALLOC_SIMPLE (due to its nature) is never freed.
  751. {
  752.     // Not checked because even if it's not VAR_NORMAL, there are few if any consequences to continuing.
  753.     //if (mType != VAR_NORMAL) // For robustness, since callers generally shouldn't call it this way.
  754.     //    return;
  755.  
  756.     if (mType == VAR_ALIAS) // For simplicity and reduced code size, just make a recursive call to self.
  757.     {
  758.         if (!aExcludeAliases)
  759.             // For maintainability, it seems best not to use the following method:
  760.             //    Var &var = *(mType == VAR_ALIAS ? mAliasFor : this);
  761.             // If that were done, bugs would be easy to introduce in a long function like this one
  762.             // if your forget at use the implicit "this" by accident.  So instead, just call self.
  763.             mAliasFor->Free(aWhenToFree);
  764.         //else caller didn't want the target of the alias freed, so do nothing.
  765.         return;
  766.     }
  767.  
  768.     // Must check this one first because caller relies not only on var not being freed in this case,
  769.     // but also on its contents not being set to an empty string:
  770.     if (aWhenToFree == VAR_ALWAYS_FREE_BUT_EXCLUDE_STATIC && (mAttrib & VAR_ATTRIB_STATIC))
  771.         return; // This is the only case in which the variable ISN'T made blank.
  772.  
  773.     mLength = 0; // Writing to union is safe because above already ensured that "this" isn't an alias.
  774.     mAttrib &= ~VAR_ATTRIB_BINARY_CLIP; // Even if it isn't free'd, variable will be made blank. So it seems proper to always remove the binary_clip attribute (since it can't be used that way after it's been made blank).
  775.  
  776.     switch (mHowAllocated)
  777.     {
  778.     // Shouldn't be necessary to check the following because by definition, ALLOC_NONE
  779.     // means mContents==sEmptyString (this policy is enforced in other places).
  780.     //
  781.     //case ALLOC_NONE:
  782.     //    mContents = sEmptyString;
  783.     //    break;
  784.  
  785.     case ALLOC_SIMPLE:
  786.         // Don't set to sEmptyString because then we'd have a memory leak.  i.e. once a var becomes
  787.         // ALLOC_SIMPLE, it should never become ALLOC_NONE again (though it can become ALLOC_MALLOC).
  788.         *mContents = '\0';
  789.         break;
  790.  
  791.     case ALLOC_MALLOC:
  792.         // Setting a var whose contents are very large to be nothing or blank is currently the
  793.         // only way to free up the memory of that var.  Shrinking it dynamically seems like it
  794.         // might introduce too much memory fragmentation and overhead (since in many cases,
  795.         // it would likely need to grow back to its former size in the near future).  So we
  796.         // only free relatively large vars:
  797.         if (mCapacity)
  798.         {
  799.             // aWhenToFree==VAR_FREE_IF_LARGE: the memory is not freed if it is a small area because
  800.             // it might help reduce memory fragmentation amd improve performance in cases where
  801.             // the memory will soon be needed again (in which case one free+malloc is saved).
  802.             if (   aWhenToFree < VAR_ALWAYS_FREE_LAST  // Fixed for v1.0.40.07 to prevent memory leak in recursive script-function calls.
  803.                 || aWhenToFree == VAR_FREE_IF_LARGE && mCapacity > (4 * 1024)   )
  804.             {
  805.                 free(mContents);
  806.                 mCapacity = 0;             // Invariant: Anyone setting mCapacity to 0 must also set
  807.                 mContents = sEmptyString;  // mContents to the empty string.
  808.                 // BUT DON'T CHANGE mHowAllocated to ALLOC_NONE (see comments further below).
  809.             }
  810.             else // Don't actually free it, but make it blank (callers rely on this).
  811.                 *mContents = '\0';
  812.         }
  813.         //else mCapacity==0, so mContents is already the empty string, so don't attempt to free
  814.         // it or assign to it. It was the responsibility of whoever set mCapacity to 0 to ensure mContents
  815.         // was set properly (which is why it's not done here).
  816.  
  817.         // But do not change mHowAllocated to be ALLOC_NONE because it would cause a
  818.         // a memory leak in this sequence of events:
  819.         // var1 is assigned something short enough to make it ALLOC_SIMPLE
  820.         // var1 is assigned something large enough to require malloc()
  821.         // var1 is set to empty string and its mem is thus free()'d by the above.
  822.         // var1 is once again assigned something short enough to make it ALLOC_SIMPLE
  823.         // The last step above would be a problem because the 2nd ALLOC_SIMPLE can't
  824.         // reclaim the spot in SimpleHeap that had been in use by the first.  In other
  825.         // words, when a var makes the transition from ALLOC_SIMPLE to ALLOC_MALLOC,
  826.         // its ALLOC_SIMPLE memory is lost to the system until the program exits.
  827.         // But since this loss occurs at most once per distinct variable name,
  828.         // it's not considered a memory leak because the loss can't exceed a fixed
  829.         // amount regardless of how long the program runs.  The reason for all of this
  830.         // is that allocating dynamic memory is costly: it causes system memory fragmentation,
  831.         // (especially if a var were to be malloc'd and free'd thousands of times in a loop)
  832.         // and small-sized mallocs have a large overhead: it's been said that every block
  833.         // of dynamic mem, even those of size 1 or 2, incurs about 40 bytes of overhead
  834.         // (and testing of SimpleHeap supports this).
  835.         // UPDATE: Yes it's true that a script could create an unlimited number of new variables
  836.         // by constantly using different dynamic names when creating them.  But it's still supportable
  837.         // that there's no memory leak because even if the worst-case series of events mentioned
  838.         // higher above occurs for every variable, only a fixed amount of memory is ever lost per
  839.         // variable.  So you could think of the lost memory as part of the basic overhead of creating
  840.         // a variable (since variables are never truly destroyed, just their contents freed).
  841.         // The odds against all of these worst-case factors occurring simultaneously in anything other
  842.         // than a theoretical test script seem nearly astronomical.
  843.         break;
  844.     } // switch()
  845. }
  846.  
  847.  
  848.  
  849. ResultType Var::AppendIfRoom(char *aStr, VarSizeType aLength)
  850. // Returns OK if there's room enough to append aStr and it succeeds.
  851. // Returns FAIL otherwise (also returns FAIL for VAR_CLIPBOARD).
  852. // Environment variables aren't supported here; instead, aStr is appended directly onto the actual/internal
  853. // contents of the "this" variable.
  854. {
  855.     // Relies on the fact that aliases can't point to other aliases (enforced by UpdateAlias()):
  856.     Var &var = *(mType == VAR_ALIAS ? mAliasFor : this);
  857.     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.
  858.         return FAIL; // CHECK THIS FIRST, BEFORE BELOW, BECAUSE CALLERS ALWAYS WANT IT TO BE A FAILURE.
  859.     if (!aLength) // Consider the appending of nothing (even onto unsupported things like clipboard) to be a success.
  860.         return OK;
  861.     VarSizeType var_length = 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.
  862.     VarSizeType new_length = var_length + aLength;
  863.     if (new_length >= var.mCapacity) // Not enough room.
  864.         return FAIL;
  865.     memmove(var.mContents + var_length, aStr, aLength);  // memmove() vs. memcpy() in case there's any overlap between source and dest.
  866.     var.mContents[new_length] = '\0'; // Terminate it as a separate step in case caller passed a length shorter than the apparent length of aStr.
  867.     var.mLength = new_length;
  868.     // If this is a binary-clip variable, appending has probably "corrupted" it; so don't allow it to ever be
  869.     // put back onto the clipboard as binary data (the routine that does that is designed to detect corruption,
  870.     // but it might not be perfect since corruption is so rare).
  871.     var.mAttrib &= ~VAR_ATTRIB_BINARY_CLIP;
  872.     return OK;
  873. }
  874.  
  875.  
  876.  
  877. void Var::AcceptNewMem(char *aNewMem, VarSizeType aLength)
  878. // Caller provides a new malloc'd memory block (currently must be non-NULL).  That block and its
  879. // contents are directly hung onto this variable in place of its old block, which is freed (except
  880. // in the case of VAR_CLIPBOARD, in which case the memory is copied onto the clipboard then freed).
  881. // Caller must ensure that mType == VAR_NORMAL or VAR_CLIPBOARD.
  882. // This function was added in v1.0.45 to aid callers in improving performance.
  883. {
  884.     // Relies on the fact that aliases can't point to other aliases (enforced by UpdateAlias()).
  885.     Var &var = *(mType == VAR_ALIAS ? mAliasFor : this);
  886.     if (var.mType == VAR_CLIPBOARD)
  887.     {
  888.         var.Assign(aNewMem, aLength); // Clipboard requires GlobalAlloc memory so can't directly accept aNewMem.  So just copy it the normal way.
  889.         free(aNewMem); // Caller gave it to us to take charge of, but we have no further use for it.
  890.     }
  891.     else // VAR_NORMAL
  892.     {
  893.         var.Free(VAR_ALWAYS_FREE); // Release the variable's old memory.
  894.         var.mHowAllocated = ALLOC_MALLOC; // Must always be this type to avoid complications and possible memory leaks.
  895.         var.mAttrib &= ~VAR_ATTRIB_BINARY_CLIP; // New memory is always non-binary-clip.  A new parameter could be added to change this if it's ever needed.
  896.         var.mContents = aNewMem;
  897.         var.mLength = aLength;
  898.         var.mCapacity = (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.
  899.         // Shrink the memory if there's a lot of wasted space because the extra capacity is seldom utilized
  900.         // in real-world scripts.
  901.         // A simple rule seems best because shrinking is probably fast regardless of the sizes involved,
  902.         // plus and there's consierable rarity to ever needing capacity beyond what's in a variable
  903.         // (concat/append is one example).  This will leave a large percentage of extra space in small variables,
  904.         // but in those rare cases when a script needs to create thousands of such variables, there may be a
  905.         // current or future way to shrink an existing variable to contain only its current length, such as
  906.         // VarShrink().
  907.         if (var.mCapacity - var.mLength > 64)
  908.         {
  909.             var.mCapacity = var.mLength + 1; // This will become the new capacity.
  910.             // _expand() is only about 75 bytes of uncompressed code size and probably performs very quickly
  911.             // when shrinking.  Also, MSDN implies that when shrinking, failure won't happen unless something
  912.             // is terribly wrong (e.g. corrupted heap).  But for robustness it is checked anyway:
  913.             if (   !(var.mContents = (char *)_expand(var.mContents, var.mCapacity))   )
  914.             {
  915.                 var.mLength = 0;
  916.                 var.mCapacity = 0;
  917.             }
  918.         }
  919.     }
  920. }
  921.  
  922.  
  923.  
  924. void Var::SetLengthFromContents()
  925. // Function added in v1.0.43.06.  It updates the mLength member to reflect the actual current length of mContents.
  926. {
  927.     // Relies on the fact that aliases can't point to other aliases (enforced by UpdateAlias()).
  928.     Var &var = *(mType == VAR_ALIAS ? mAliasFor : this);
  929.     VarSizeType capacity = var.Capacity();
  930.     // Below uses Contents() and Length() vs. direct members for better maintainability, even though
  931.     // it might not be strictly necessary.
  932.     char *contents = var.Contents();
  933.     if (capacity > 0)
  934.     {
  935.          contents[capacity - 1] = '\0';  // Caller wants us to ensure it's terminated, to avoid crashing strlen() below.
  936.         var.mLength = (VarSizeType)strlen(contents);
  937.     }
  938.     //else it has no capacity, so do nothing (it could also be a reserved/built-in variable).
  939. }
  940.  
  941.  
  942.  
  943. ResultType Var::BackupFunctionVars(Func &aFunc, VarBkp *&aVarBackup, int &aVarBackupCount)
  944. // All parameters except the first are output parameters that are set for our caller (though caller
  945. // is responsible for having initialized aVarBackup to NULL).
  946. // If there is nothing to backup, only the aVarBackupCount is changed (to zero).
  947. // Returns OK or FAIL.
  948. {
  949.     if (   !(aVarBackupCount = aFunc.mVarCount + aFunc.mLazyVarCount)   )  // Nothing needs to be backed up.
  950.         return OK; // Leave aVarBackup set to NULL as set by the caller.
  951.  
  952.     // NOTES ABOUT MALLOC(): Apparently, the implementation of malloc() is quite good, at least for small blocks
  953.     // needed to back up 50 or less variables.  It nearly as fast as alloca(), at least when the system
  954.     // isn't under load and has the memory to spare without swapping.  Therefore, the attempt to use alloca to
  955.     // speed up recursive script-functions didn't result in enough of a speed-up (only 1 to 5%) to be worth the
  956.     // added complexity.
  957.     // Since Var is not a POD struct (it contains private members, a custom constructor, etc.), the VarBkp
  958.     // POD struct is used to hold the backup because it's probably better performance than using Var's
  959.     // constructor to create each backup array element.
  960.     if (   !(aVarBackup = (VarBkp *)malloc(aVarBackupCount * sizeof(VarBkp)))   ) // Caller will take care of freeing it.
  961.         return FAIL;
  962.  
  963.     int i;
  964.     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.
  965.  
  966.     // Note that Backup() does not make the variable empty after backing it up because that is something
  967.     // that must be done by our caller at a later stage.
  968.     for (i = 0; i < aFunc.mVarCount; ++i)
  969.         if (!(aFunc.mVar[i]->mAttrib & VAR_ATTRIB_STATIC)) // Don't bother backing up statics because they won't need to be restored.
  970.             aFunc.mVar[i]->Backup(aVarBackup[aVarBackupCount++]);
  971.     for (i = 0; i < aFunc.mLazyVarCount; ++i)
  972.         if (!(aFunc.mLazyVar[i]->mAttrib & VAR_ATTRIB_STATIC)) // Don't bother backing up statics because they won't need to be restored.
  973.             aFunc.mLazyVar[i]->Backup(aVarBackup[aVarBackupCount++]);
  974.     return OK;
  975. }
  976.  
  977.  
  978.  
  979. void Var::Backup(VarBkp &aVarBkp)
  980. // Caller must not call this function for static variables because it's not equipped to deal with them
  981. // (they don't need to be backed up or restored anyway).
  982. // This method is used rather than struct copy (=) because it's of expected higher performance than
  983. // using the Var::constructor to make a copy of each var.  Also note that something like memcpy()
  984. // can't be used on Var objects since they're not POD (e.g. they have a contructor and they have
  985. // private members).
  986. {
  987.     aVarBkp.mVar = this; // Allows the restoration process to always know its target without searching.
  988.     aVarBkp.mContents = mContents;
  989.     aVarBkp.mLength = mLength; // Since it's a union, it might actually be backing up mAliasFor (happens at least for recursive functions that pass parameters ByRef).
  990.     aVarBkp.mCapacity = mCapacity;
  991.     aVarBkp.mHowAllocated = mHowAllocated; // This might be ALLOC_SIMPLE or ALLOC_NONE if backed up variable was at the lowest layer of the call stack.
  992.     aVarBkp.mAttrib = mAttrib;
  993.     // Once the backup is made, Free() is not called because the whole point of the backup is to
  994.     // preserve the original memory/contents of each variable.  Instead, clear the variable
  995.     // completely and set it up to become ALLOC_MALLOC in case anything actually winds up using
  996.     // the variable prior to the restoration of the backup.  In other words, ALLOC_SIMPLE and NONE
  997.     // retained (if present) because that would cause a memory leak when multiple layers are all
  998.     // allowed to use ALLOC_SIMPLE yet none are ever able to free it (the bottommost layer is
  999.     // allowed to use ALLOC_SIMPLE because that's a fixed/constant amount of memory gets freed
  1000.     // when the program exits).
  1001.     // Now reset this variable (caller has ensured it's non-static) to create a "new layer" for it, keeping
  1002.     // its backup intact but allowing this variable (or formal parameter) to be given a new value in the future:
  1003.     mCapacity = 0;             // Invariant: Anyone setting mCapacity to 0 must also set...
  1004.     mContents = sEmptyString;  // ...mContents to the empty string.
  1005.     if (mType != VAR_ALIAS) // Fix for v1.0.42.07: Don't reset mLength if the other member of the union is in effect.
  1006.         mLength = 0;        // Otherwise, functions that recursively pass ByRef parameters can crash because mType stays as VAR_ALIAS.
  1007.     mHowAllocated = ALLOC_MALLOC; // Never NONE because that would permit SIMPLE. See comments higher above.
  1008.     mAttrib &= ~VAR_ATTRIB_BINARY_CLIP; // But the VAR_ATTRIB_STATIC flag isn't altered.
  1009. }
  1010.  
  1011.  
  1012.  
  1013. void Var::FreeAndRestoreFunctionVars(Func &aFunc, VarBkp *&aVarBackup, int &aVarBackupCount)
  1014. {
  1015.     int i;
  1016.     for (i = 0; i < aFunc.mVarCount; ++i)
  1017.         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).
  1018.     for (i = 0; i < aFunc.mLazyVarCount; ++i)
  1019.         aFunc.mLazyVar[i]->Free(VAR_ALWAYS_FREE_BUT_EXCLUDE_STATIC, true);
  1020.  
  1021.     // The freeing (above) MUST be done prior to the restore-from-backup below (otherwise there would be
  1022.     // a memory leak).  Static variables are never backed up and thus do not exist in the aVarBackup array.
  1023.     // This is because by definition, the contents of statics are not freed or altered by the calling procedure
  1024.     // (regardless how how recursive or multi-threaded the function is).
  1025.     if (aVarBackup) // This is the indicator that a backup was made; thus a restore is also needed.
  1026.     {
  1027.         for (i = 0; i < aVarBackupCount; ++i) // Static variables were never backed up so they won't be in this array. See comments above.
  1028.         {
  1029.             VarBkp &bkp = aVarBackup[i]; // Resolve only once for performance.
  1030.             Var &var = *bkp.mVar;        //
  1031.             var.mContents = bkp.mContents;
  1032.             var.mLength = bkp.mLength; // Since it's a union, it might actually be restoring mAliasFor, which is desired.
  1033.             var.mCapacity = bkp.mCapacity;
  1034.             var.mHowAllocated = bkp.mHowAllocated; // This might be ALLOC_SIMPLE or ALLOC_NONE if backed up variable was at the lowest layer of the call stack.
  1035.             var.mAttrib = bkp.mAttrib;
  1036.         }
  1037.         free(aVarBackup);
  1038.         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.
  1039.     }
  1040. }
  1041.  
  1042.  
  1043.  
  1044. ResultType Var::ValidateName(char *aName, bool aIsRuntime, int aDisplayError)
  1045. // Returns OK or FAIL.
  1046. {
  1047.     if (!*aName) return FAIL;
  1048.     // Seems best to disallow variables that start with numbers so that more advanced
  1049.     // parsing (e.g. expressions) can be more easily added in the future.  UPDATE: For
  1050.     // backward compatibility with AutoIt2's technique of storing command line args in
  1051.     // a numically-named var (e.g. %1% is the first arg), decided not to do this:
  1052.     //if (*aName >= '0' && *aName <= '9')
  1053.     //    return g_script.ScriptError("This variable name starts with a number, which is not allowed.", aName);
  1054.     for (char c, *cp = aName; *cp; ++cp)
  1055.     {
  1056.         // ispunct(): @ # $ _ [ ] ? ! % & " ' ( ) * + - ^ . / \ : ; , < = > ` ~ | { }
  1057.         // Of the above, it seems best to disallow the following:
  1058.         // () future: user-defined functions, e.g. var = myfunc2(myfunc1() + 2)
  1059.         // ! future "not"
  1060.         // % reserved: deref char
  1061.         // & future: "and" or "bitwise and"
  1062.         // ' seems too iffy
  1063.         // " seems too iffy
  1064.         // */-+ reserved: math
  1065.         // , reserved: delimiter
  1066.         // . future: structs
  1067.         // : seems too iffy
  1068.         // ; reserved: comment
  1069.         // \ seems too iffy
  1070.         // <=> reserved: comparison
  1071.         // ^ future: "exp/power"
  1072.         // ` reserved: escape char
  1073.         // {} reserved: blocks
  1074.         // | future: "or" or "bitwise or"
  1075.         // ~ future: "bitwise not"
  1076.  
  1077.         // Rewritten for v1.0.36.02 to enhance performance and also forbid characters such as linefeed and
  1078.         // alert/bell inside variable names.  Ordered to maximize short-circuit performance for the most-often
  1079.         // used characters in variables names:
  1080.         c = *cp;  // For performance.
  1081.         if ((c < 'a' || c > 'z') && (c < 'A' || c > 'Z') && (c < '0' || c > '9') // It's not a core/legacy alphanumberic.
  1082.             && c >= 0 // It's not an extended ASCII character such as Ç/╢/┐ (for simplicity and backward compatibility, these are always allowed).
  1083.             && !strchr("_[]$?#@", c)) // It's not a permitted punctunation mark.
  1084.         {
  1085.             if (aDisplayError)
  1086.             {
  1087.                 char msg[512];
  1088.                 snprintf(msg, sizeof(msg), "The following %s name contains an illegal character:\n\"%-1.300s\"%s"
  1089.                     , aDisplayError == DISPLAY_VAR_ERROR ? "variable" : "function"
  1090.                     , aName
  1091.                     , aIsRuntime ? ("\n\n" ERR_ABORT_NO_SPACES) : "");
  1092.                 return g_script.ScriptError(msg);
  1093.             }
  1094.             else
  1095.                 return FAIL;
  1096.         }
  1097.     }
  1098.     // Otherwise:
  1099.     return OK;
  1100. }
  1101.