PageRenderTime 128ms CodeModel.GetById 26ms RepoModel.GetById 0ms app.codeStats 1ms

/Source/script.cpp

https://github.com/Geargia/AutoHotkey
C++ | 9651 lines | 7330 code | 411 blank | 1910 comment | 1500 complexity | 61daa4a3e240093c68914366f52d2ccc MD5 | raw file
Possible License(s): AGPL-1.0, BSD-3-Clause
  1. /*
  2. AutoHotkey
  3. Copyright 2003-2009 Chris Mallett (support@autohotkey.com)
  4. This program is free software; you can redistribute it and/or
  5. modify it under the terms of the GNU General Public License
  6. as published by the Free Software Foundation; either version 2
  7. of the License, or (at your option) any later version.
  8. This program is distributed in the hope that it will be useful,
  9. but WITHOUT ANY WARRANTY; without even the implied warranty of
  10. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  11. GNU General Public License for more details.
  12. */
  13. #include "stdafx.h" // pre-compiled headers
  14. #include "script.h"
  15. #include "globaldata.h" // for a lot of things
  16. #include "util.h" // for strlcpy() etc.
  17. #include "mt19937ar-cok.h" // for random number generator
  18. #include "window.h" // for a lot of things
  19. #include "application.h" // for MsgSleep()
  20. // Globals that are for only this module:
  21. #define MAX_COMMENT_FLAG_LENGTH 15
  22. static char g_CommentFlag[MAX_COMMENT_FLAG_LENGTH + 1] = ";"; // Adjust the below for any changes.
  23. static size_t g_CommentFlagLength = 1; // pre-calculated for performance
  24. // General note about the methods in here:
  25. // Want to be able to support multiple simultaneous points of execution
  26. // because more than one subroutine can be executing simultaneously
  27. // (well, more precisely, there can be more than one script subroutine
  28. // that's in a "currently running" state, even though all such subroutines,
  29. // except for the most recent one, are suspended. So keep this in mind when
  30. // using things such as static data members or static local variables.
  31. Script::Script()
  32. : mFirstLine(NULL), mLastLine(NULL), mCurrLine(NULL), mPlaceholderLabel(NULL), mLineCount(0)
  33. , mThisHotkeyName(""), mPriorHotkeyName(""), mThisHotkeyStartTime(0), mPriorHotkeyStartTime(0)
  34. , mEndChar(0), mThisHotkeyModifiersLR(0)
  35. , mNextClipboardViewer(NULL), mOnClipboardChangeIsRunning(false), mOnClipboardChangeLabel(NULL)
  36. , mOnExitLabel(NULL), mExitReason(EXIT_NONE)
  37. , mFirstLabel(NULL), mLastLabel(NULL)
  38. , mFirstFunc(NULL), mLastFunc(NULL)
  39. , mFirstTimer(NULL), mLastTimer(NULL), mTimerEnabledCount(0), mTimerCount(0)
  40. , mFirstMenu(NULL), mLastMenu(NULL), mMenuCount(0)
  41. , mVar(NULL), mVarCount(0), mVarCountMax(0), mLazyVar(NULL), mLazyVarCount(0)
  42. , mCurrentFuncOpenBlockCount(0), mNextLineIsFunctionBody(false)
  43. , mFuncExceptionVar(NULL), mFuncExceptionVarCount(0)
  44. , mCurrFileIndex(0), mCombinedLineNumber(0), mNoHotkeyLabels(true), mMenuUseErrorLevel(false)
  45. , mFileSpec(""), mFileDir(""), mFileName(""), mOurEXE(""), mOurEXEDir(""), mMainWindowTitle("")
  46. , mIsReadyToExecute(false), mAutoExecSectionIsRunning(false)
  47. , mIsRestart(false), mIsAutoIt2(false), mErrorStdOut(false)
  48. #ifdef AUTOHOTKEYSC
  49. , mCompiledHasCustomIcon(false)
  50. #else
  51. , mIncludeLibraryFunctionsThenExit(NULL)
  52. #endif
  53. , mLinesExecutedThisCycle(0), mUninterruptedLineCountMax(1000), mUninterruptibleTime(15)
  54. , mRunAsUser(NULL), mRunAsPass(NULL), mRunAsDomain(NULL)
  55. , mCustomIcon(NULL) // Normally NULL unless there's a custom tray icon loaded dynamically.
  56. , mCustomIconFile(NULL), mIconFrozen(false), mTrayIconTip(NULL) // Allocated on first use.
  57. , mCustomIconNumber(0)
  58. {
  59. // v1.0.25: mLastScriptRest and mLastPeekTime are now initialized right before the auto-exec
  60. // section of the script is launched, which avoids an initial Sleep(10) in ExecUntil
  61. // that would otherwise occur.
  62. *mThisMenuItemName = *mThisMenuName = '\0';
  63. ZeroMemory(&mNIC, sizeof(mNIC)); // Constructor initializes this, to be safe.
  64. mNIC.hWnd = NULL; // Set this as an indicator that it tray icon is not installed.
  65. // Lastly (after the above have been initialized), anything that can fail:
  66. if ( !(mTrayMenu = AddMenu("Tray")) ) // realistically never happens
  67. {
  68. ScriptError("No tray mem");
  69. ExitApp(EXIT_CRITICAL);
  70. }
  71. else
  72. mTrayMenu->mIncludeStandardItems = true;
  73. #ifdef _DEBUG
  74. if (ID_FILE_EXIT < ID_MAIN_FIRST) // Not a very thorough check.
  75. ScriptError("DEBUG: ID_FILE_EXIT is too large (conflicts with IDs reserved via ID_USER_FIRST).");
  76. if (MAX_CONTROLS_PER_GUI > ID_USER_FIRST - 3)
  77. ScriptError("DEBUG: MAX_CONTROLS_PER_GUI is too large (conflicts with IDs reserved via ID_USER_FIRST).");
  78. int LargestMaxParams, i, j;
  79. ActionTypeType *np;
  80. // Find the Largest value of MaxParams used by any command and make sure it
  81. // isn't something larger than expected by the parsing routines:
  82. for (LargestMaxParams = i = 0; i < g_ActionCount; ++i)
  83. {
  84. if (g_act[i].MaxParams > LargestMaxParams)
  85. LargestMaxParams = g_act[i].MaxParams;
  86. // This next part has been tested and it does work, but only if one of the arrays
  87. // contains exactly MAX_NUMERIC_PARAMS number of elements and isn't zero terminated.
  88. // Relies on short-circuit boolean order:
  89. for (np = g_act[i].NumericParams, j = 0; j < MAX_NUMERIC_PARAMS && *np; ++j, ++np);
  90. if (j >= MAX_NUMERIC_PARAMS)
  91. {
  92. ScriptError("DEBUG: At least one command has a NumericParams array that isn't zero-terminated."
  93. " This would result in reading beyond the bounds of the array.");
  94. return;
  95. }
  96. }
  97. if (LargestMaxParams > MAX_ARGS)
  98. ScriptError("DEBUG: At least one command supports more arguments than allowed.");
  99. if (sizeof(ActionTypeType) == 1 && g_ActionCount > 256)
  100. ScriptError("DEBUG: Since there are now more than 256 Action Types, the ActionTypeType"
  101. " typedef must be changed.");
  102. #endif
  103. }
  104. Script::~Script() // Destructor.
  105. {
  106. // MSDN: "Before terminating, an application must call the UnhookWindowsHookEx function to free
  107. // system resources associated with the hook."
  108. AddRemoveHooks(0); // Remove all hooks.
  109. if (mNIC.hWnd) // Tray icon is installed.
  110. Shell_NotifyIcon(NIM_DELETE, &mNIC); // Remove it.
  111. // Destroy any Progress/SplashImage windows that haven't already been destroyed. This is necessary
  112. // because sometimes these windows aren't owned by the main window:
  113. int i;
  114. for (i = 0; i < MAX_PROGRESS_WINDOWS; ++i)
  115. {
  116. if (g_Progress[i].hwnd && IsWindow(g_Progress[i].hwnd))
  117. DestroyWindow(g_Progress[i].hwnd);
  118. if (g_Progress[i].hfont1) // Destroy font only after destroying the window that uses it.
  119. DeleteObject(g_Progress[i].hfont1);
  120. if (g_Progress[i].hfont2) // Destroy font only after destroying the window that uses it.
  121. DeleteObject(g_Progress[i].hfont2);
  122. if (g_Progress[i].hbrush)
  123. DeleteObject(g_Progress[i].hbrush);
  124. }
  125. for (i = 0; i < MAX_SPLASHIMAGE_WINDOWS; ++i)
  126. {
  127. if (g_SplashImage[i].pic)
  128. g_SplashImage[i].pic->Release();
  129. if (g_SplashImage[i].hwnd && IsWindow(g_SplashImage[i].hwnd))
  130. DestroyWindow(g_SplashImage[i].hwnd);
  131. if (g_SplashImage[i].hfont1) // Destroy font only after destroying the window that uses it.
  132. DeleteObject(g_SplashImage[i].hfont1);
  133. if (g_SplashImage[i].hfont2) // Destroy font only after destroying the window that uses it.
  134. DeleteObject(g_SplashImage[i].hfont2);
  135. if (g_SplashImage[i].hbrush)
  136. DeleteObject(g_SplashImage[i].hbrush);
  137. }
  138. // It is safer/easier to destroy the GUI windows prior to the menus (especially the menu bars).
  139. // This is because one GUI window might get destroyed and take with it a menu bar that is still
  140. // in use by an existing GUI window. GuiType::Destroy() adheres to this philosophy by detaching
  141. // its menu bar prior to destroying its window:
  142. for (i = 0; i < MAX_GUI_WINDOWS; ++i)
  143. GuiType::Destroy(i); // Static method to avoid problems with object destroying itself.
  144. for (i = 0; i < GuiType::sFontCount; ++i) // Now that GUI windows are gone, delete all GUI fonts.
  145. if (GuiType::sFont[i].hfont)
  146. DeleteObject(GuiType::sFont[i].hfont);
  147. // The above might attempt to delete an HFONT from GetStockObject(DEFAULT_GUI_FONT), etc.
  148. // But that should be harmless:
  149. // MSDN: "It is not necessary (but it is not harmful) to delete stock objects by calling DeleteObject."
  150. // Above: Probably best to have removed icon from tray and destroyed any Gui/Splash windows that were
  151. // using it prior to getting rid of the script's custom icon below:
  152. if (mCustomIcon)
  153. DestroyIcon(mCustomIcon);
  154. // Since they're not associated with a window, we must free the resources for all popup menus.
  155. // Update: Even if a menu is being used as a GUI window's menu bar, see note above for why menu
  156. // destruction is done AFTER the GUI windows are destroyed:
  157. UserMenu *menu_to_delete;
  158. for (UserMenu *m = mFirstMenu; m;)
  159. {
  160. menu_to_delete = m;
  161. m = m->mNextMenu;
  162. ScriptDeleteMenu(menu_to_delete);
  163. // Above call should not return FAIL, since the only way FAIL can realistically happen is
  164. // when a GUI window is still using the menu as its menu bar. But all GUI windows are gone now.
  165. }
  166. // Since tooltip windows are unowned, they should be destroyed to avoid resource leak:
  167. for (i = 0; i < MAX_TOOLTIPS; ++i)
  168. if (g_hWndToolTip[i] && IsWindow(g_hWndToolTip[i]))
  169. DestroyWindow(g_hWndToolTip[i]);
  170. if (g_hFontSplash) // The splash window itself should auto-destroyed, since it's owned by main.
  171. DeleteObject(g_hFontSplash);
  172. if (mOnClipboardChangeLabel) // Remove from viewer chain.
  173. ChangeClipboardChain(g_hWnd, mNextClipboardViewer);
  174. // Close any open sound item to prevent hang-on-exit in certain operating systems or conditions.
  175. // If there's any chance that a sound was played and not closed out, or that it is still playing,
  176. // this check is done. Otherwise, the check is avoided since it might be a high overhead call,
  177. // especially if the sound subsystem part of the OS is currently swapped out or something:
  178. if (g_SoundWasPlayed)
  179. {
  180. char buf[MAX_PATH * 2];
  181. mciSendString("status " SOUNDPLAY_ALIAS " mode", buf, sizeof(buf), NULL);
  182. if (*buf) // "playing" or "stopped"
  183. mciSendString("close " SOUNDPLAY_ALIAS, NULL, 0, NULL);
  184. }
  185. #ifdef ENABLE_KEY_HISTORY_FILE
  186. KeyHistoryToFile(); // Close the KeyHistory file if it's open.
  187. #endif
  188. DeleteCriticalSection(&g_CriticalRegExCache); // g_CriticalRegExCache is used elsewhere for thread-safety.
  189. }
  190. ResultType Script::Init(global_struct &g, char *aScriptFilename, bool aIsRestart)
  191. // Returns OK or FAIL.
  192. // Caller has provided an empty string for aScriptFilename if this is a compiled script.
  193. // Otherwise, aScriptFilename can be NULL if caller hasn't determined the filename of the script yet.
  194. {
  195. mIsRestart = aIsRestart;
  196. char buf[2048]; // Just to make sure we have plenty of room to do things with.
  197. #ifdef AUTOHOTKEYSC
  198. // Fix for v1.0.29: Override the caller's use of __argv[0] by using GetModuleFileName(),
  199. // so that when the script is started from the command line but the user didn't type the
  200. // extension, the extension will be included. This necessary because otherwise
  201. // #SingleInstance wouldn't be able to detect duplicate versions in every case.
  202. // It also provides more consistency.
  203. GetModuleFileName(NULL, buf, sizeof(buf));
  204. #else
  205. if (!aScriptFilename) // v1.0.46.08: Change in policy: store the default script in the My Documents directory rather than in Program Files. It's more correct and solves issues that occur due to Vista's file-protection scheme.
  206. {
  207. // Since no script-file was specified on the command line, use the default name.
  208. // For backward compatibility, FIRST check if there's an AutoHotkey.ini file in the current
  209. // directory. If there is, that needs to be used to retain compatibility.
  210. aScriptFilename = NAME_P ".ini";
  211. if (GetFileAttributes(aScriptFilename) == 0xFFFFFFFF) // File doesn't exist, so fall back to new method.
  212. {
  213. aScriptFilename = buf;
  214. VarSizeType filespec_length = BIV_MyDocuments(aScriptFilename, ""); // e.g. C:\Documents and Settings\Home\My Documents
  215. if (filespec_length > sizeof(buf)-16) // Need room for 16 characters ('\\' + "AutoHotkey.ahk" + terminator).
  216. return FAIL; // Very rare, so for simplicity just abort.
  217. strcpy(aScriptFilename + filespec_length, "\\AutoHotkey.ahk"); // Append the filename: .ahk vs. .ini seems slightly better in terms of clarity and usefulness (e.g. the ability to double click the default script to launch it).
  218. // Now everything is set up right because even if aScriptFilename is a nonexistent file, the
  219. // user will be prompted to create it by a stage further below.
  220. }
  221. //else since the legacy .ini file exists, everything is now set up right. (The file might be a directory, but that isn't checked due to rarity.)
  222. }
  223. // In case the script is a relative filespec (relative to current working dir):
  224. char *unused;
  225. if (!GetFullPathName(aScriptFilename, sizeof(buf), buf, &unused)) // This is also relied upon by mIncludeLibraryFunctionsThenExit. Succeeds even on nonexistent files.
  226. return FAIL; // Due to rarity, no error msg, just abort.
  227. #endif
  228. // Using the correct case not only makes it look better in title bar & tray tool tip,
  229. // it also helps with the detection of "this script already running" since otherwise
  230. // it might not find the dupe if the same script name is launched with different
  231. // lowercase/uppercase letters:
  232. ConvertFilespecToCorrectCase(buf); // This might change the length, e.g. due to expansion of 8.3 filename.
  233. char *filename_marker;
  234. if ( !(filename_marker = strrchr(buf, '\\')) )
  235. filename_marker = buf;
  236. else
  237. ++filename_marker;
  238. if ( !(mFileSpec = SimpleHeap::Malloc(buf)) ) // The full spec is stored for convenience, and it's relied upon by mIncludeLibraryFunctionsThenExit.
  239. return FAIL; // It already displayed the error for us.
  240. filename_marker[-1] = '\0'; // Terminate buf in this position to divide the string.
  241. size_t filename_length = strlen(filename_marker);
  242. if ( mIsAutoIt2 = (filename_length >= 4 && !stricmp(filename_marker + filename_length - 4, EXT_AUTOIT2)) )
  243. {
  244. // Set the old/AutoIt2 defaults for maximum safety and compatibilility.
  245. // Standalone EXEs (compiled scripts) are always considered to be non-AutoIt2 (otherwise,
  246. // the user should probably be using the AutoIt2 compiler).
  247. g_AllowSameLineComments = false;
  248. g_EscapeChar = '\\';
  249. g.TitleFindFast = true; // In case the normal default is false.
  250. g.DetectHiddenText = false;
  251. // Make the mouse fast like AutoIt2, but not quite insta-move. 2 is expected to be more
  252. // reliable than 1 since the AutoIt author said that values less than 2 might cause the
  253. // drag to fail (perhaps just for specific apps, such as games):
  254. g.DefaultMouseSpeed = 2;
  255. g.KeyDelay = 20;
  256. g.WinDelay = 500;
  257. g.LinesPerCycle = 1;
  258. g.IntervalBeforeRest = -1; // i.e. this method is disabled by default for AutoIt2 scripts.
  259. // Reduce max params so that any non escaped delimiters the user may be using literally
  260. // in "window text" will still be considered literal, rather than as delimiters for
  261. // args that are not supported by AutoIt2, such as exclude-title, exclude-text, MsgBox
  262. // timeout, etc. Note: Don't need to change IfWinExist and such because those already
  263. // have special handling to recognize whether exclude-title is really a valid command
  264. // instead (e.g. IfWinExist, title, text, Gosub, something).
  265. // NOTE: DO NOT ADD the IfWin command series to this section, since there is special handling
  266. // for parsing those commands to figure out whether they're being used in the old AutoIt2
  267. // style or the new Exclude Title/Text mode.
  268. // v1.0.40.02: The following is no longer done because a different mechanism is required now
  269. // that the ARGn macros do not check whether mArgc is too small and substitute an empty string
  270. // (instead, there is a loop in ExpandArgs that puts an empty string in each sArgDeref entry
  271. // for which the script omitted a parameter [and that loop relies on MaxParams being absolutely
  272. // accurate rather than conditional upon whether the script is of type ".aut"]).
  273. //g_act[ACT_FILESELECTFILE].MaxParams -= 2;
  274. //g_act[ACT_FILEREMOVEDIR].MaxParams -= 1;
  275. //g_act[ACT_MSGBOX].MaxParams -= 1;
  276. //g_act[ACT_INIREAD].MaxParams -= 1;
  277. //g_act[ACT_STRINGREPLACE].MaxParams -= 1;
  278. //g_act[ACT_STRINGGETPOS].MaxParams -= 2;
  279. //g_act[ACT_WINCLOSE].MaxParams -= 3; // -3 for these two, -2 for the others.
  280. //g_act[ACT_WINKILL].MaxParams -= 3;
  281. //g_act[ACT_WINACTIVATE].MaxParams -= 2;
  282. //g_act[ACT_WINMINIMIZE].MaxParams -= 2;
  283. //g_act[ACT_WINMAXIMIZE].MaxParams -= 2;
  284. //g_act[ACT_WINRESTORE].MaxParams -= 2;
  285. //g_act[ACT_WINHIDE].MaxParams -= 2;
  286. //g_act[ACT_WINSHOW].MaxParams -= 2;
  287. //g_act[ACT_WINSETTITLE].MaxParams -= 2;
  288. //g_act[ACT_WINGETTITLE].MaxParams -= 2;
  289. }
  290. if ( !(mFileDir = SimpleHeap::Malloc(buf)) )
  291. return FAIL; // It already displayed the error for us.
  292. if ( !(mFileName = SimpleHeap::Malloc(filename_marker)) )
  293. return FAIL; // It already displayed the error for us.
  294. #ifdef AUTOHOTKEYSC
  295. // Omit AutoHotkey from the window title, like AutoIt3 does for its compiled scripts.
  296. // One reason for this is to reduce backlash if evil-doers create viruses and such
  297. // with the program:
  298. snprintf(buf, sizeof(buf), "%s\\%s", mFileDir, mFileName);
  299. #else
  300. snprintf(buf, sizeof(buf), "%s\\%s - %s", mFileDir, mFileName, NAME_PV);
  301. #endif
  302. if ( !(mMainWindowTitle = SimpleHeap::Malloc(buf)) )
  303. return FAIL; // It already displayed the error for us.
  304. // It may be better to get the module name this way rather than reading it from the registry
  305. // (though it might be more proper to parse it out of the command line args or something),
  306. // in case the user has moved it to a folder other than the install folder, hasn't installed it,
  307. // or has renamed the EXE file itself. Also, enclose the full filespec of the module in double
  308. // quotes since that's how callers usually want it because ActionExec() currently needs it that way:
  309. *buf = '"';
  310. if (GetModuleFileName(NULL, buf + 1, sizeof(buf) - 2)) // -2 to leave room for the enclosing double quotes.
  311. {
  312. size_t buf_length = strlen(buf);
  313. buf[buf_length++] = '"';
  314. buf[buf_length] = '\0';
  315. if ( !(mOurEXE = SimpleHeap::Malloc(buf)) )
  316. return FAIL; // It already displayed the error for us.
  317. else
  318. {
  319. char *last_backslash = strrchr(buf, '\\');
  320. if (!last_backslash) // probably can't happen due to the nature of GetModuleFileName().
  321. mOurEXEDir = "";
  322. last_backslash[1] = '\0'; // i.e. keep the trailing backslash for convenience.
  323. if ( !(mOurEXEDir = SimpleHeap::Malloc(buf + 1)) ) // +1 to omit the leading double-quote.
  324. return FAIL; // It already displayed the error for us.
  325. }
  326. }
  327. return OK;
  328. }
  329. ResultType Script::CreateWindows()
  330. // Returns OK or FAIL.
  331. {
  332. if (!mMainWindowTitle || !*mMainWindowTitle) return FAIL; // Init() must be called before this function.
  333. // Register a window class for the main window:
  334. WNDCLASSEX wc = {0};
  335. wc.cbSize = sizeof(wc);
  336. wc.lpszClassName = WINDOW_CLASS_MAIN;
  337. wc.hInstance = g_hInstance;
  338. wc.lpfnWndProc = MainWindowProc;
  339. // The following are left at the default of NULL/0 set higher above:
  340. //wc.style = 0; // CS_HREDRAW | CS_VREDRAW
  341. //wc.cbClsExtra = 0;
  342. //wc.cbWndExtra = 0;
  343. wc.hIcon = wc.hIconSm = (HICON)LoadImage(g_hInstance, MAKEINTRESOURCE(IDI_MAIN), IMAGE_ICON, 0, 0, LR_SHARED); // Use LR_SHARED to conserve memory (since the main icon is loaded for so many purposes).
  344. wc.hCursor = LoadCursor((HINSTANCE) NULL, IDC_ARROW);
  345. wc.hbrBackground = (HBRUSH)(COLOR_BTNFACE + 1); // Needed for ProgressBar. Old: (HBRUSH)GetStockObject(WHITE_BRUSH);
  346. wc.lpszMenuName = MAKEINTRESOURCE(IDR_MENU_MAIN); // NULL; // "MainMenu";
  347. if (!RegisterClassEx(&wc))
  348. {
  349. MsgBox("RegClass"); // Short/generic msg since so rare.
  350. return FAIL;
  351. }
  352. // Register a second class for the splash window. The only difference is that
  353. // it doesn't have the menu bar:
  354. wc.lpszClassName = WINDOW_CLASS_SPLASH;
  355. wc.lpszMenuName = NULL; // Override the non-NULL value set higher above.
  356. if (!RegisterClassEx(&wc))
  357. {
  358. MsgBox("RegClass"); // Short/generic msg since so rare.
  359. return FAIL;
  360. }
  361. char class_name[64];
  362. HWND fore_win = GetForegroundWindow();
  363. bool do_minimize = !fore_win || (GetClassName(fore_win, class_name, sizeof(class_name))
  364. && !stricmp(class_name, "Shell_TrayWnd")); // Shell_TrayWnd is the taskbar's class on Win98/XP and probably the others too.
  365. // Note: the title below must be constructed the same was as is done by our
  366. // WinMain() (so that we can detect whether this script is already running)
  367. // which is why it's standardized in g_script.mMainWindowTitle.
  368. // Create the main window. Prevent momentary disruption of Start Menu, which
  369. // some users understandably don't like, by omitting the taskbar button temporarily.
  370. // This is done because testing shows that minimizing the window further below, even
  371. // though the window is hidden, would otherwise briefly show the taskbar button (or
  372. // at least redraw the taskbar). Sometimes this isn't noticeable, but other times
  373. // (such as when the system is under heavy load) a user reported that it is quite
  374. // noticeable. WS_EX_TOOLWINDOW is used instead of WS_EX_NOACTIVATE because
  375. // WS_EX_NOACTIVATE is available only on 2000/XP.
  376. if ( !(g_hWnd = CreateWindowEx(do_minimize ? WS_EX_TOOLWINDOW : 0
  377. , WINDOW_CLASS_MAIN
  378. , mMainWindowTitle
  379. , WS_OVERLAPPEDWINDOW // Style. Alt: WS_POPUP or maybe 0.
  380. , CW_USEDEFAULT // xpos
  381. , CW_USEDEFAULT // ypos
  382. , CW_USEDEFAULT // width
  383. , CW_USEDEFAULT // height
  384. , NULL // parent window
  385. , NULL // Identifies a menu, or specifies a child-window identifier depending on the window style
  386. , g_hInstance // passed into WinMain
  387. , NULL)) ) // lpParam
  388. {
  389. MsgBox("CreateWindow"); // Short msg since so rare.
  390. return FAIL;
  391. }
  392. #ifdef AUTOHOTKEYSC
  393. HMENU menu = GetMenu(g_hWnd);
  394. // Disable the Edit menu item, since it does nothing for a compiled script:
  395. EnableMenuItem(menu, ID_FILE_EDITSCRIPT, MF_DISABLED | MF_GRAYED);
  396. EnableOrDisableViewMenuItems(menu, MF_DISABLED | MF_GRAYED); // Fix for v1.0.47.06: No point in checking g_AllowMainWindow because the script hasn't starting running yet, so it will always be false.
  397. // But leave the ID_VIEW_REFRESH menu item enabled because if the script contains a
  398. // command such as ListLines in it, Refresh can be validly used.
  399. #endif
  400. if ( !(g_hWndEdit = CreateWindow("edit", NULL, WS_CHILD | WS_VISIBLE | WS_BORDER
  401. | ES_LEFT | ES_MULTILINE | ES_READONLY | WS_VSCROLL // | WS_HSCROLL (saves space)
  402. , 0, 0, 0, 0, g_hWnd, (HMENU)1, g_hInstance, NULL)) )
  403. {
  404. MsgBox("CreateWindow"); // Short msg since so rare.
  405. return FAIL;
  406. }
  407. // FONTS: The font used by default, at least on XP, is GetStockObject(SYSTEM_FONT).
  408. // It seems preferable to smaller fonts such DEFAULT_GUI_FONT(DEFAULT_GUI_FONT).
  409. // For more info on pre-loaded fonts (not too many choices), see MSDN's GetStockObject().
  410. //SendMessage(g_hWndEdit, WM_SETFONT, (WPARAM)GetStockObject(SYSTEM_FONT), 0);
  411. // v1.0.30.05: Specifying a limit of zero opens the control to its maximum text capacity,
  412. // which removes the 32K size restriction. Testing shows that this does not increase the actual
  413. // amount of memory used for controls containing small amounts of text. All it does is allow
  414. // the control to allocate more memory as needed. By specifying zero, a max
  415. // of 64K becomes available on Windows 9x, and perhaps as much as 4 GB on NT/2k/XP.
  416. SendMessage(g_hWndEdit, EM_LIMITTEXT, 0, 0);
  417. // Some of the MSDN docs mention that an app's very first call to ShowWindow() makes that
  418. // function operate in a special mode. Therefore, it seems best to get that first call out
  419. // of the way to avoid the possibility that the first-call behavior will cause problems with
  420. // our normal use of ShowWindow() below and other places. Also, decided to ignore nCmdShow,
  421. // to avoid any momentary visual effects on startup.
  422. // Update: It's done a second time because the main window might now be visible if the process
  423. // that launched ours specified that. It seems best to override the requested state because
  424. // some calling processes might specify "maximize" or "shownormal" as generic launch method.
  425. // The script can display it's own main window with ListLines, etc.
  426. // MSDN: "the nCmdShow value is ignored in the first call to ShowWindow if the program that
  427. // launched the application specifies startup information in the structure. In this case,
  428. // ShowWindow uses the information specified in the STARTUPINFO structure to show the window.
  429. // On subsequent calls, the application must call ShowWindow with nCmdShow set to SW_SHOWDEFAULT
  430. // to use the startup information provided by the program that launched the application."
  431. ShowWindow(g_hWnd, SW_HIDE);
  432. ShowWindow(g_hWnd, SW_HIDE);
  433. // Now that the first call to ShowWindow() is out of the way, minimize the main window so that
  434. // if the script is launched from the Start Menu (and perhaps other places such as the
  435. // Quick-launch toolbar), the window that was active before the Start Menu was displayed will
  436. // become active again. But as of v1.0.25.09, this minimize is done more selectively to prevent
  437. // the launch of a script from knocking the user out of a full-screen game or other application
  438. // that would be disrupted by an SW_MINIMIZE:
  439. if (do_minimize)
  440. {
  441. ShowWindow(g_hWnd, SW_MINIMIZE);
  442. SetWindowLong(g_hWnd, GWL_EXSTYLE, 0); // Give the main window back its taskbar button.
  443. }
  444. // Note: When the window is not minimized, task manager reports that a simple script (such as
  445. // one consisting only of the single line "#Persistent") uses 2600 KB of memory vs. ~452 KB if
  446. // it were immediately minimized. That is probably just due to the vagaries of how the OS
  447. // manages windows and memory and probably doesn't actually impact system performance to the
  448. // degree indicated. In other words, it's hard to imagine that the failure to do
  449. // ShowWidnow(g_hWnd, SW_MINIMIZE) unconditionally upon startup (which causes the side effects
  450. // discussed further above) significantly increases the actual memory load on the system.
  451. g_hAccelTable = LoadAccelerators(g_hInstance, MAKEINTRESOURCE(IDR_ACCELERATOR1));
  452. if (g_NoTrayIcon)
  453. mNIC.hWnd = NULL; // Set this as an indicator that tray icon is not installed.
  454. else
  455. // Even if the below fails, don't return FAIL in case the user is using a different shell
  456. // or something. In other words, it is expected to fail under certain circumstances and
  457. // we want to tolerate that:
  458. CreateTrayIcon();
  459. if (mOnClipboardChangeLabel)
  460. mNextClipboardViewer = SetClipboardViewer(g_hWnd);
  461. return OK;
  462. }
  463. void Script::EnableOrDisableViewMenuItems(HMENU aMenu, UINT aFlags)
  464. {
  465. EnableMenuItem(aMenu, ID_VIEW_KEYHISTORY, aFlags);
  466. EnableMenuItem(aMenu, ID_VIEW_LINES, aFlags);
  467. EnableMenuItem(aMenu, ID_VIEW_VARIABLES, aFlags);
  468. EnableMenuItem(aMenu, ID_VIEW_HOTKEYS, aFlags);
  469. }
  470. void Script::CreateTrayIcon()
  471. // It is the caller's responsibility to ensure that the previous icon is first freed/destroyed
  472. // before calling us to install a new one. However, that is probably not needed if the Explorer
  473. // crashed, since the memory used by the tray icon was probably destroyed along with it.
  474. {
  475. ZeroMemory(&mNIC, sizeof(mNIC)); // To be safe.
  476. // Using NOTIFYICONDATA_V2_SIZE vs. sizeof(NOTIFYICONDATA) improves compatibility with Win9x maybe.
  477. // MSDN: "Using [NOTIFYICONDATA_V2_SIZE] for cbSize will allow your application to use NOTIFYICONDATA
  478. // with earlier Shell32.dll versions, although without the version 6.0 enhancements."
  479. // Update: Using V2 gives an compile error so trying V1. Update: Trying sizeof(NOTIFYICONDATA)
  480. // for compatibility with VC++ 6.x. This is also what AutoIt3 uses:
  481. mNIC.cbSize = sizeof(NOTIFYICONDATA); // NOTIFYICONDATA_V1_SIZE
  482. mNIC.hWnd = g_hWnd;
  483. mNIC.uID = AHK_NOTIFYICON; // This is also used for the ID, see TRANSLATE_AHK_MSG for details.
  484. mNIC.uFlags = NIF_MESSAGE | NIF_TIP | NIF_ICON;
  485. mNIC.uCallbackMessage = AHK_NOTIFYICON;
  486. #ifdef AUTOHOTKEYSC
  487. // i.e. don't override the user's custom icon:
  488. mNIC.hIcon = mCustomIcon ? mCustomIcon : (HICON)LoadImage(g_hInstance, MAKEINTRESOURCE(mCompiledHasCustomIcon ? IDI_MAIN : g_IconTray), IMAGE_ICON, 0, 0, LR_SHARED);
  489. #else
  490. mNIC.hIcon = mCustomIcon ? mCustomIcon : (HICON)LoadImage(g_hInstance, MAKEINTRESOURCE(g_IconTray), IMAGE_ICON, 0, 0, LR_SHARED); // Use LR_SHARED to conserve memory (since the main icon is loaded for so many purposes).
  491. #endif
  492. UPDATE_TIP_FIELD
  493. // If we were called due to an Explorer crash, I don't think it's necessary to call
  494. // Shell_NotifyIcon() to remove the old tray icon because it was likely destroyed
  495. // along with Explorer. So just add it unconditionally:
  496. if (!Shell_NotifyIcon(NIM_ADD, &mNIC))
  497. mNIC.hWnd = NULL; // Set this as an indicator that tray icon is not installed.
  498. }
  499. void Script::UpdateTrayIcon(bool aForceUpdate)
  500. {
  501. if (!mNIC.hWnd) // tray icon is not installed
  502. return;
  503. static bool icon_shows_paused = false;
  504. static bool icon_shows_suspended = false;
  505. if (!aForceUpdate && (mIconFrozen || (g->IsPaused == icon_shows_paused && g_IsSuspended == icon_shows_suspended)))
  506. return; // it's already in the right state
  507. int icon;
  508. if (g->IsPaused && g_IsSuspended)
  509. icon = IDI_PAUSE_SUSPEND;
  510. else if (g->IsPaused)
  511. icon = IDI_PAUSE;
  512. else if (g_IsSuspended)
  513. icon = g_IconTraySuspend;
  514. else
  515. #ifdef AUTOHOTKEYSC
  516. icon = mCompiledHasCustomIcon ? IDI_MAIN : g_IconTray; // i.e. don't override the user's custom icon.
  517. #else
  518. icon = g_IconTray;
  519. #endif
  520. // Use the custom tray icon if the icon is normal (non-paused & non-suspended):
  521. mNIC.hIcon = (mCustomIcon && (mIconFrozen || (!g->IsPaused && !g_IsSuspended))) ? mCustomIcon
  522. : (HICON)LoadImage(g_hInstance, MAKEINTRESOURCE(icon), IMAGE_ICON, 0, 0, LR_SHARED); // Use LR_SHARED for simplicity and performance more than to conserve memory in this case.
  523. if (Shell_NotifyIcon(NIM_MODIFY, &mNIC))
  524. {
  525. icon_shows_paused = g->IsPaused;
  526. icon_shows_suspended = g_IsSuspended;
  527. }
  528. // else do nothing, just leave it in the same state.
  529. }
  530. ResultType Script::AutoExecSection()
  531. // Returns FAIL if can't run due to critical error. Otherwise returns OK.
  532. {
  533. // Now that g_MaxThreadsTotal has been permanently set by the processing of script directives like
  534. // #MaxThreads, an appropriately sized array can be allocated:
  535. if ( !(g_array = (global_struct *)malloc((g_MaxThreadsTotal+TOTAL_ADDITIONAL_THREADS) * sizeof(global_struct))) )
  536. return FAIL; // Due to rarity, just abort. It wouldn't be safe to run ExitApp() due to possibility of an OnExit routine.
  537. CopyMemory(g_array, g, sizeof(global_struct)); // Copy the temporary/startup "g" into array[0] to preserve historical behaviors that may rely on the idle thread starting with that "g".
  538. g = g_array; // Must be done after above.
  539. // v1.0.48: Due to switching from SET_UNINTERRUPTIBLE_TIMER to IsInterruptible():
  540. // In spite of the comments in IsInterruptible(), periodically have a timer call IsInterruptible() due to
  541. // the following scenario:
  542. // - Interrupt timeout is 60 seconds (or 60 milliseconds for that matter).
  543. // - For some reason IsInterrupt() isn't called for 24+ hours even though there is a current/active thread.
  544. // - RefreshInterruptibility() fires at 23 hours and marks the thread interruptible.
  545. // - Sometime after that, one of the following happens:
  546. // Computer is suspended/hibernated and stays that way for 50+ days.
  547. // IsInterrupt() is never called (except by RefreshInterruptibility()) for 50+ days.
  548. // (above is currently unlikely because MSG_FILTER_MAX calls IsInterruptible())
  549. // In either case, RefreshInterruptibility() has prevented the uninterruptibility duration from being
  550. // wrongly extended by up to 100% of g_script.mUninterruptibleTime. This isn't a big deal if
  551. // g_script.mUninterruptibleTime is low (like it almost always is); but if it's fairly large, say an hour,
  552. // this can prevent an unwanted extension of up to 1 hour.
  553. // Although any call frequency less than 49.7 days should work, currently calling once per 23 hours
  554. // in case any older operating systems have a SetTimer() limit of less than 0x7FFFFFFF (and also to make
  555. // it less likely that a long suspend/hibernate would cause the above issue). The following was
  556. // actually tested on Windows XP and a message does indeed arrive 23 hours after the script starts.
  557. SetTimer(g_hWnd, TIMER_ID_REFRESH_INTERRUPTIBILITY, 23*60*60*1000, RefreshInterruptibility); // 3rd param must not exceed 0x7FFFFFFF (2147483647; 24.8 days).
  558. ResultType ExecUntil_result;
  559. if (!mFirstLine) // In case it's ever possible to be empty.
  560. ExecUntil_result = OK;
  561. // And continue on to do normal exit routine so that the right ExitCode is returned by the program.
  562. else
  563. {
  564. // Choose a timeout that's a reasonable compromise between the following competing priorities:
  565. // 1) That we want hotkeys to be responsive as soon as possible after the program launches
  566. // in case the user launches by pressing ENTER on a script, for example, and then immediately
  567. // tries to use a hotkey. In addition, we want any timed subroutines to start running ASAP
  568. // because in rare cases the user might rely upon that happening.
  569. // 2) To support the case when the auto-execute section never finishes (such as when it contains
  570. // an infinite loop to do background processing), yet we still want to allow the script
  571. // to put custom defaults into effect globally (for things such as KeyDelay).
  572. // Obviously, the above approach has its flaws; there are ways to construct a script that would
  573. // result in unexpected behavior. However, the combination of this approach with the fact that
  574. // the global defaults are updated *again* when/if the auto-execute section finally completes
  575. // raises the expectation of proper behavior to a very high level. In any case, I'm not sure there
  576. // is any better approach that wouldn't break existing scripts or require a redesign of some kind.
  577. // If this method proves unreliable due to disk activity slowing the program down to a crawl during
  578. // the critical milliseconds after launch, one thing that might fix that is to have ExecUntil()
  579. // be forced to run a minimum of, say, 100 lines (if there are that many) before allowing the
  580. // timer expiration to have its effect. But that's getting complicated and I'd rather not do it
  581. // unless someone actually reports that such a thing ever happens. Still, to reduce the chance
  582. // of such a thing ever happening, it seems best to boost the timeout from 50 up to 100:
  583. SET_AUTOEXEC_TIMER(100);
  584. mAutoExecSectionIsRunning = true;
  585. // v1.0.25: This is now done here, closer to the actual execution of the first line in the script,
  586. // to avoid an unnecessary Sleep(10) that would otherwise occur in ExecUntil:
  587. mLastScriptRest = mLastPeekTime = GetTickCount();
  588. ++g_nThreads;
  589. ExecUntil_result = mFirstLine->ExecUntil(UNTIL_RETURN); // Might never return (e.g. infinite loop or ExitApp).
  590. --g_nThreads;
  591. // Our caller will take care of setting g_default properly.
  592. KILL_AUTOEXEC_TIMER // See also: AutoExecSectionTimeout().
  593. mAutoExecSectionIsRunning = false;
  594. }
  595. // REMEMBER: The ExecUntil() call above will never return if the AutoExec section never finishes
  596. // (e.g. infinite loop) or it uses Exit/ExitApp.
  597. // The below is done even if AutoExecSectionTimeout() already set the values once.
  598. // This is because when the AutoExecute section finally does finish, by definition it's
  599. // supposed to store the global settings that are currently in effect as the default values.
  600. // In other words, the only purpose of AutoExecSectionTimeout() is to handle cases where
  601. // the AutoExecute section takes a long time to complete, or never completes (perhaps because
  602. // it is being used by the script as a "backround thread" of sorts):
  603. // Save the values of KeyDelay, WinDelay etc. in case they were changed by the auto-execute part
  604. // of the script. These new defaults will be put into effect whenever a new hotkey subroutine
  605. // is launched. Each launched subroutine may then change the values for its own purposes without
  606. // affecting the settings for other subroutines:
  607. global_clear_state(*g); // Start with a "clean slate" in both g_default and g (in case things like InitNewThread() check some of the values in g prior to launching a new thread).
  608. // Always want g_default.AllowInterruption==true so that InitNewThread() doesn't have to
  609. // set it except when Critical or "Thread Interrupt" require it. If the auto-execute section ended
  610. // without anyone needing to call IsInterruptible() on it, AllowInterruption could be false
  611. // even when Critical is off.
  612. // Even if the still-running AutoExec section has turned on Critical, the assignment below is still okay
  613. // because InitNewThread() adjusts AllowInterruption based on the value of ThreadIsCritical.
  614. // See similar code in AutoExecSectionTimeout().
  615. g->AllowThreadToBeInterrupted = true; // Mostly for the g_default line below. See comments above.
  616. CopyMemory(&g_default, g, sizeof(global_struct)); // g->IsPaused has been set to false higher above in case it's ever possible that it's true as a result of AutoExecSection().
  617. // After this point, the values in g_default should never be changed.
  618. global_maximize_interruptibility(*g); // See below.
  619. // Now that any changes made by the AutoExec section have been saved to g_default (including
  620. // the commands Critical and Thread), ensure that the very first g-item is always interruptible.
  621. // This avoids having to treat the first g-item as special in various places.
  622. // It seems best to set ErrorLevel to NONE after the auto-execute part of the script is done.
  623. // However, it isn't set to NONE right before launching each new thread (e.g. hotkey subroutine)
  624. // because it's more flexible that way (i.e. the user may want one hotkey subroutine to use the value
  625. // of ErrorLevel set by another). This reset was also done by LoadFromFile(), but it is done again
  626. // here in case the auto-execute section changed it:
  627. g_ErrorLevel->Assign(ERRORLEVEL_NONE);
  628. // BEFORE DOING THE BELOW, "g" and "g_default" should be set up properly in case there's an OnExit
  629. // routine (even non-persistent scripts can have one).
  630. // If no hotkeys are in effect, the user hasn't requested a hook to be activated, and the script
  631. // doesn't contain the #Persistent directive we're done unless there is an OnExit subroutine and it
  632. // doesn't do "ExitApp":
  633. if (!IS_PERSISTENT) // Resolve macro again in case any of its components changed since the last time.
  634. g_script.ExitApp(ExecUntil_result == FAIL ? EXIT_ERROR : EXIT_EXIT);
  635. return OK;
  636. }
  637. ResultType Script::Edit()
  638. {
  639. #ifdef AUTOHOTKEYSC
  640. return OK; // Do nothing.
  641. #else
  642. // This is here in case a compiled script ever uses the Edit command. Since the "Edit This
  643. // Script" menu item is not available for compiled scripts, it can't be called from there.
  644. TitleMatchModes old_mode = g->TitleMatchMode;
  645. g->TitleMatchMode = FIND_ANYWHERE;
  646. HWND hwnd = WinExist(*g, mFileName, "", mMainWindowTitle, ""); // Exclude our own main window.
  647. g->TitleMatchMode = old_mode;
  648. if (hwnd)
  649. {
  650. char class_name[32];
  651. GetClassName(hwnd, class_name, sizeof(class_name));
  652. if (!strcmp(class_name, "#32770") || !strnicmp(class_name, "AutoHotkey", 10)) // MessageBox(), InputBox(), FileSelectFile(), or GUI/script-owned window.
  653. hwnd = NULL; // Exclude it from consideration.
  654. }
  655. if (hwnd) // File appears to already be open for editing, so use the current window.
  656. SetForegroundWindowEx(hwnd);
  657. else
  658. {
  659. char buf[MAX_PATH * 2];
  660. // Enclose in double quotes anything that might contain spaces since the CreateProcess()
  661. // method, which is attempted first, is more likely to succeed. This is because it uses
  662. // the command line method of creating the process, with everything all lumped together:
  663. snprintf(buf, sizeof(buf), "\"%s\"", mFileSpec);
  664. if (!ActionExec("edit", buf, mFileDir, false)) // Since this didn't work, try notepad.
  665. {
  666. // v1.0.40.06: Try to open .ini files first with their associated editor rather than trying the
  667. // "edit" verb on them:
  668. char *file_ext;
  669. if ( !(file_ext = strrchr(mFileName, '.')) || stricmp(file_ext, ".ini")
  670. || !ActionExec("open", buf, mFileDir, false) ) // Relies on short-circuit boolean order.
  671. {
  672. // Even though notepad properly handles filenames with spaces in them under WinXP,
  673. // even without double quotes around them, it seems safer and more correct to always
  674. // enclose the filename in double quotes for maximum compatibility with all OSes:
  675. if (!ActionExec("notepad.exe", buf, mFileDir, false))
  676. MsgBox("Could not open script."); // Short message since so rare.
  677. }
  678. }
  679. }
  680. return OK;
  681. #endif
  682. }
  683. ResultType Script::Reload(bool aDisplayErrors)
  684. {
  685. // The new instance we're about to start will tell our process to stop, or it will display
  686. // a syntax error or some other error, in which case our process will still be running:
  687. #ifdef AUTOHOTKEYSC
  688. // This is here in case a compiled script ever uses the Reload command. Since the "Reload This
  689. // Script" menu item is not available for compiled scripts, it can't be called from there.
  690. return g_script.ActionExec(mOurEXE, "/restart", g_WorkingDirOrig, aDisplayErrors);
  691. #else
  692. char arg_string[MAX_PATH + 512];
  693. snprintf(arg_string, sizeof(arg_string), "/restart \"%s\"", mFileSpec);
  694. return g_script.ActionExec(mOurEXE, arg_string, g_WorkingDirOrig, aDisplayErrors);
  695. #endif
  696. }
  697. ResultType Script::ExitApp(ExitReasons aExitReason, char *aBuf, int aExitCode)
  698. // Normal exit (if aBuf is NULL), or a way to exit immediately on error (which is mostly
  699. // for times when it would be unsafe to call MsgBox() due to the possibility that it would
  700. // make the situation even worse).
  701. {
  702. mExitReason = aExitReason;
  703. bool terminate_afterward = aBuf && !*aBuf;
  704. if (aBuf && *aBuf)
  705. {
  706. char buf[1024];
  707. // No more than size-1 chars will be written and string will be terminated:
  708. snprintf(buf, sizeof(buf), "Critical Error: %s\n\n" WILL_EXIT, aBuf);
  709. // To avoid chance of more errors, don't use MsgBox():
  710. MessageBox(g_hWnd, buf, g_script.mFileSpec, MB_OK | MB_SETFOREGROUND | MB_APPLMODAL);
  711. TerminateApp(CRITICAL_ERROR); // Only after the above.
  712. }
  713. // Otherwise, it's not a critical error. Note that currently, mOnExitLabel can only be
  714. // non-NULL if the script is in a runnable state (since registering an OnExit label requires
  715. // that a script command has executed to do it). If this ever changes, the !mIsReadyToExecute
  716. // condition should be added to the below if statement:
  717. static bool sExitLabelIsRunning = false;
  718. if (!mOnExitLabel || sExitLabelIsRunning) // || !mIsReadyToExecute
  719. // In the case of sExitLabelIsRunning == true:
  720. // There is another instance of this function beneath us on the stack. Since we have
  721. // been called, this is a true exit condition and we exit immediately.
  722. // MUST NOT create a new thread when sExitLabelIsRunning because g_array allows only one
  723. // extra thread for ExitApp() (which allows it to run even when MAX_THREADS_EMERGENCY has
  724. // been reached). See TOTAL_ADDITIONAL_THREADS.
  725. TerminateApp(aExitCode);
  726. // Otherwise, the script contains the special RunOnExit label that we will run here instead
  727. // of exiting. And since it does, we know that the script is in a ready-to-execute state
  728. // because that is the only way an OnExit label could have been defined in the first place.
  729. // Usually, the RunOnExit subroutine will contain an Exit or ExitApp statement
  730. // which results in a recursive call to this function, but this is not required (e.g. the
  731. // Exit subroutine could display an "Are you sure?" prompt, and if the user chooses "No",
  732. // the Exit sequence can be aborted by simply not calling ExitApp and letting the thread
  733. // we create below end normally).
  734. // Next, save the current state of the globals so that they can be restored just prior
  735. // to returning to our caller:
  736. char ErrorLevel_saved[ERRORLEVEL_SAVED_SIZE];
  737. strlcpy(ErrorLevel_saved, g_ErrorLevel->Contents(), sizeof(ErrorLevel_saved)); // Save caller's errorlevel.
  738. InitNewThread(0, true, true, ACT_INVALID); // Uninterruptibility is handled below. Since this special thread should always run, no checking of g_MaxThreadsTotal is done before calling this.
  739. // Turn on uninterruptibility to forbid any hotkeys, timers, or user defined menu items
  740. // to interrupt. This is mainly done for peace-of-mind (since possible interactions due to
  741. // interruptions have not been studied) and the fact that this most users would not want this
  742. // subroutine to be interruptible (it usually runs quickly anyway). Another reason to make
  743. // it non-interruptible is that some OnExit subroutines might destruct things used by the
  744. // script's hotkeys/timers/menu items, and activating these items during the deconstruction
  745. // would not be safe. Finally, if a logoff or shutdown is occurring, it seems best to prevent
  746. // timed subroutines from running -- which might take too much time and prevent the exit from
  747. // occurring in a timely fashion. An option can be added via the FutureUse param to make it
  748. // interruptible if there is ever a demand for that.
  749. // UPDATE: g_AllowInterruption is now used instead of g->AllowThreadToBeInterrupted for two reasons:
  750. // 1) It avoids the need to do "int mUninterruptedLineCountMax_prev = g_script.mUninterruptedLineCountMax;"
  751. // (Disable this item so that ExecUntil() won't automatically make our new thread uninterruptible
  752. // after it has executed a certain number of lines).
  753. // 2) Mostly obsolete: If the thread we're interrupting is uninterruptible, the uinterruptible timer
  754. // might be currently pending. When it fires, it would make the OnExit subroutine interruptible
  755. // rather than the underlying subroutine. The above fixes the first part of that problem.
  756. // The 2nd part is fixed by reinstating the timer when the uninterruptible thread is resumed.
  757. // This special handling is only necessary here -- not in other places where new threads are
  758. // created -- because OnExit is the only type of thread that can interrupt an uninterruptible
  759. // thread.
  760. BOOL g_AllowInterruption_prev = g_AllowInterruption; // Save current setting.
  761. g_AllowInterruption = FALSE; // Mark the thread just created above as permanently uninterruptible (i.e. until it finishes and is destroyed).
  762. sExitLabelIsRunning = true;
  763. if (mOnExitLabel->Execute() == FAIL)
  764. // If the subroutine encounters a failure condition such as a runtime error, exit immediately.
  765. // Otherwise, there will be no way to exit the script if the subroutine fails on each attempt.
  766. TerminateApp(aExitCode);
  767. sExitLabelIsRunning = false; // In case the user wanted the thread to end normally (see above).
  768. if (terminate_afterward)
  769. TerminateApp(aExitCode);
  770. // Otherwise:
  771. ResumeUnderlyingThread(ErrorLevel_saved);
  772. g_AllowInterruption = g_AllowInterruption_prev; // Restore original setting.
  773. return OK; // for caller convenience.
  774. }
  775. void Script::TerminateApp(int aExitCode)
  776. // Note that g_script's destructor takes care of most other cleanup work, such as destroying
  777. // tray icons, menus, and unowned windows such as ToolTip.
  778. {
  779. // We call DestroyWindow() because MainWindowProc() has left that up to us.
  780. // DestroyWindow() will cause MainWindowProc() to immediately receive and process the
  781. // WM_DESTROY msg, which should in turn result in any child windows being destroyed
  782. // and other cleanup being done:
  783. if (IsWindow(g_hWnd)) // Adds peace of mind in case WM_DESTROY was already received in some unusual way.
  784. {
  785. g_DestroyWindowCalled = true;
  786. DestroyWindow(g_hWnd);
  787. }
  788. Hotkey::AllDestructAndExit(aExitCode);
  789. }
  790. #ifdef AUTOHOTKEYSC
  791. LineNumberType Script::LoadFromFile()
  792. #else
  793. LineNumberType Script::LoadFromFile(bool aScriptWasNotspecified)
  794. #endif
  795. // Returns the number of non-comment lines that were loaded, or LOADING_FAILED on error.
  796. {
  797. mNoHotkeyLabels = true; // Indicate that there are no hotkey labels, since we're (re)loading the entire file.
  798. mIsReadyToExecute = mAutoExecSectionIsRunning = false;
  799. if (!mFileSpec || !*mFileSpec) return LOADING_FAILED;
  800. #ifndef AUTOHOTKEYSC // When not in stand-alone mode, read an external script file.
  801. DWORD attr = GetFileAttributes(mFileSpec);
  802. if (attr == MAXDWORD) // File does not exist or lacking the authorization to get its attributes.
  803. {
  804. char buf[MAX_PATH + 256];
  805. if (aScriptWasNotspecified) // v1.0.46.09: Give a more descriptive prompt to help users get started.
  806. {
  807. snprintf(buf, sizeof(buf),
  808. "To help you get started, would you like to create a sample script in the My Documents folder?\n"
  809. "\n"
  810. "Press YES to create and display the sample script.\n"
  811. "Press NO to exit.\n");
  812. }
  813. else // Mostly for backward compatibility, also prompt to create if an explicitly specified script doesn't exist.
  814. snprintf(buf, sizeof(buf), "The script file \"%s\" does not exist. Create it now?", mFileSpec);
  815. int response = MsgBox(buf, MB_YESNO);
  816. if (response != IDYES)
  817. return 0;
  818. FILE *fp2 = fopen(mFileSpec, "a");
  819. if (!fp2)
  820. {
  821. MsgBox("Could not create file, perhaps because the current directory is read-only"
  822. " or has insufficient permissions.");
  823. return LOADING_FAILED;
  824. }
  825. fputs(
  826. "; IMPORTANT INFO ABOUT GETTING STARTED: Lines that start with a\n"
  827. "; semicolon, such as this one, are comments. They are not executed.\n"
  828. "\n"
  829. "; This script has a special filename and path because it is automatically\n"
  830. "; launched when you run the program directly. Also, any text file whose\n"
  831. "; name ends in .ahk is associated with the program, which means that it\n"
  832. "; can be launched simply by double-clicking it. You can have as many .ahk\n"
  833. "; files as you want, located in any folder. You can also run more than\n"
  834. "; one ahk file simultaneously and each will get its own tray icon.\n"
  835. "\n"
  836. "; SAMPLE HOTKEYS: Below are two sample hotkeys. The first is Win+Z and it\n"
  837. "; launches a web site in the default browser. The second is Control+Alt+N\n"
  838. "; and it launches a new Notepad window (or activates an existing one). To\n"
  839. "; try out these hotkeys, run AutoHotkey again, which will load this file.\n"
  840. "\n"
  841. "#z::Run www.autohotkey.com\n"
  842. "\n"
  843. "^!n::\n"
  844. "IfWinExist Untitled - Notepad\n"
  845. "\tWinActivate\n"
  846. "else\n"
  847. "\tRun Notepad\n"
  848. "return\n"
  849. "\n"
  850. "\n"
  851. "; Note: From now on whenever you run AutoHotkey directly, this script\n"
  852. "; will be loaded. So feel free to customize it to suit your needs.\n"
  853. "\n"
  854. "; Please read the QUICK-START TUTORIAL near the top of the help file.\n"
  855. "; It explains how to perform common automation tasks such as sending\n"
  856. "; keystrokes and mouse clicks. It also explains more about hotkeys.\n"
  857. "\n"
  858. , fp2);
  859. fclose(fp2);
  860. // One or both of the below would probably fail -- at least on Win95 -- if mFileSpec ever
  861. // has spaces in it (since it's passed as the entire param string). So enclose the filename
  862. // in double quotes. I don't believe the directory needs to be in double quotes since it's
  863. // a separate field within the CreateProcess() and ShellExecute() structures:
  864. snprintf(buf, sizeof(buf), "\"%s\"", mFileSpec);
  865. if (!ActionExec("edit", buf, mFileDir, false))
  866. if (!ActionExec("Notepad.exe", buf, mFileDir, false))
  867. {
  868. MsgBox("Can't open script."); // Short msg since so rare.
  869. return LOADING_FAILED;
  870. }
  871. // future: have it wait for the process to close, then try to open the script again:
  872. return 0;
  873. }
  874. #endif
  875. // v1.0.42: Placeholder to use in place of a NULL label to simplify code in some places.
  876. // This must be created before loading the script because it's relied upon when creating
  877. // hotkeys to provide an alternative to having a NULL label. It will be given a non-NULL
  878. // mJumpToLine further down.
  879. if ( !(mPlaceholderLabel = new Label("")) ) // Not added to linked list since it's never looked up.
  880. return LOADING_FAILED;
  881. // Load the main script file. This will also load any files it includes with #Include.
  882. if ( LoadIncludedFile(mFileSpec, false, false) != OK
  883. || !AddLine(ACT_EXIT) // Fix for v1.0.47.04: Add an Exit because otherwise, a script that ends in an IF-statement will crash in PreparseBlocks() because PreparseBlocks() expects every IF-statements mNextLine to be non-NULL (helps loading performance too).
  884. || !PreparseBlocks(mFirstLine) ) // Must preparse the blocks before preparsing the If/Else's further below because If/Else may rely on blocks.
  885. return LOADING_FAILED; // Error was already displayed by the above calls.
  886. // ABOVE: In v1.0.47, the above may have auto-included additional files from the userlib/stdlib.
  887. // That's why the above is done prior to adding the EXIT lines and other things below.
  888. #ifndef AUTOHOTKEYSC
  889. if (mIncludeLibraryFunctionsThenExit)
  890. {
  891. fclose(mIncludeLibraryFunctionsThenExit);
  892. return 0; // Tell our caller to do a normal exit.
  893. }
  894. #endif
  895. // v1.0.35.11: Restore original working directory so that changes made to it by the above (via
  896. // "#Include C:\Scripts" or "#Include %A_ScriptDir%" or even stdlib/userlib) do not affect the
  897. // script's runtime working directory. This preserves the flexibility of having a startup-determined
  898. // working directory for the script's runtime (i.e. it seems best that the mere presence of
  899. // "#Include NewDir" should not entirely eliminate this flexibility).
  900. SetCurrentDirectory(g_WorkingDirOrig); // g_WorkingDirOrig previously set by WinMain().
  901. // Rather than do this, which seems kinda nasty if ever someday support same-line
  902. // else actions such as "else return", just add two EXITs to the end of every script.
  903. // That way, if the first EXIT added accidentally "corrects" an actionless ELSE
  904. // or IF, the second one will serve as the anchoring end-point (mRelatedLine) for that
  905. // IF or ELSE. In other words, since we never want mRelatedLine to be NULL, this should
  906. // make absolutely sure of that:
  907. //if (mLastLine->mActionType == ACT_ELSE ||
  908. // ACT_IS_IF(mLastLine->mActionType)
  909. // ...
  910. // Second ACT_EXIT: even if the last line of the script is already "exit", always add
  911. // another one in case the script ends in a label. That way, every label will have
  912. // a non-NULL target, which simplifies other aspects of script execution.
  913. // Making sure that all scripts end with an EXIT ensures that if the script
  914. // file ends with ELSEless IF or an ELSE, that IF's or ELSE's mRelatedLine
  915. // will be non-NULL, which further simplifies script execution.
  916. // Not done since it's number doesn't much matter: ++mCombinedLineNumber;
  917. ++mCombinedLineNumber; // So that the EXITs will both show up in ListLines as the line # after the last physical one in the script.
  918. if (!(AddLine(ACT_EXIT) && AddLine(ACT_EXIT))) // Second exit guaranties non-NULL mRelatedLine(s).
  919. return LOADING_FAILED;
  920. mPlaceholderLabel->mJumpToLine = mLastLine; // To follow the rule "all labels should have a non-NULL line before the script starts running".
  921. if (!PreparseIfElse(mFirstLine))
  922. return LOADING_FAILED; // Error was already displayed by the above calls.
  923. // Use FindOrAdd, not Add, because the user may already have added it simply by
  924. // referring to it in the script:
  925. if ( !(g_ErrorLevel = FindOrAddVar("ErrorLevel")) )
  926. return LOADING_FAILED; // Error. Above already displayed it for us.
  927. // Initialize the var state to zero right before running anything in the script:
  928. g_ErrorLevel->Assign(ERRORLEVEL_NONE);
  929. // Initialize the random number generator:
  930. // Note: On 32-bit hardware, the generator module uses only 2506 bytes of static
  931. // data, so it doesn't seem worthwhile to put it in a class (so that the mem is
  932. // only allocated on first use of the generator). For v1.0.24, _ftime() is not
  933. // used since it could be as large as 0.5 KB of non-compressed code. A simple call to
  934. // GetSystemTimeAsFileTime() seems just as good or better, since it produces
  935. // a FILETIME, which is "the number of 100-nanosecond intervals since January 1, 1601."
  936. // Use the low-order DWORD since the high-order one rarely changes. If my calculations are correct,
  937. // the low-order 32-bits traverses its full 32-bit range every 7.2 minutes, which seems to make
  938. // using it as a seed superior to GetTickCount for most purposes.
  939. RESEED_RANDOM_GENERATOR;
  940. return mLineCount; // The count of runnable lines that were loaded, which might be zero.
  941. }
  942. bool IsFunction(char *aBuf, bool *aPendingFunctionHasBrace = NULL)
  943. // Helper function for LoadIncludedFile().
  944. // Caller passes in an aBuf containing a candidate line such as "function(x, y)"
  945. // Caller has ensured that aBuf is rtrim'd.
  946. // Caller should pass NULL for aPendingFunctionHasBrace to indicate that function definitions (open-brace
  947. // on same line as function) are not allowed. When non-NULL *and* aBuf is a function call/def,
  948. // *aPendingFunctionHasBrace is set to true if a brace is present at the end, or false otherwise.
  949. // In addition, any open-brace is removed from aBuf in this mode.
  950. {
  951. char *action_end = StrChrAny(aBuf, EXPR_ALL_SYMBOLS EXPR_ILLEGAL_CHARS);
  952. // Can't be a function definition or call without an open-parenthesis as first char found by the above.
  953. // In addition, if action_end isn't NULL, that confirms that the string in aBuf prior to action_end contains
  954. // no spaces, tabs, colons, or equal-signs. As a result, it can't be:
  955. // 1) a hotstring, since they always start with at least one colon that would be caught immediately as
  956. // first-expr-char-is-not-open-parenthesis by the above.
  957. // 2) Any kind of math or assignment, such as var:=(x+y) or var+=(x+y).
  958. // The only things it could be other than a function call or function definition are:
  959. // Normal label that ends in single colon but contains an open-parenthesis prior to the colon, e.g. Label(x):
  960. // Single-line hotkey such as KeyName::MsgBox. But since '(' isn't valid inside KeyName, this isn't a concern.
  961. // In addition, note that it isn't necessary to check for colons that lie outside of quoted strings because
  962. // we're only interested in the first "word" of aBuf: If this is indeed a function call or definition, what
  963. // lies to the left of its first open-parenthesis can't contain any colons anyway because the above would
  964. // have caught it as first-expr-char-is-not-open-parenthesis. In other words, there's no way for a function's
  965. // opening parenthesis to occur after a legtimate/quoted colon or double-colon in its parameters.
  966. // v1.0.40.04: Added condition "action_end != aBuf" to allow a hotkey or remap or hotkey such as
  967. // such as "(::" to work even if it ends in a close-parenthesis such as "(::)" or "(::MsgBox )"
  968. if ( !(action_end && *action_end == '(' && action_end != aBuf
  969. && (action_end - aBuf != 2 || strnicmp(aBuf, "IF", 2))
  970. && (action_end - aBuf != 5 || strnicmp(aBuf, "WHILE", 5))) // v1.0.48.04: Recognize While() as loop rather than a function because many programmers are in the habit of writing while() and if().
  971. || action_end[1] == ':' ) // v1.0.44.07: This prevents "$(::fn_call()" from being seen as a function-call vs. hotkey-with-call. For simplicity and due to rarity, omit_leading_whitespace() isn't called; i.e. assumes that the colon immediate follows the '('.
  972. return false;
  973. char *aBuf_last_char = action_end + strlen(action_end) - 1; // Above has already ensured that action_end is "(...".
  974. if (aPendingFunctionHasBrace) // Caller specified that an optional open-brace may be present at the end of aBuf.
  975. {
  976. if (*aPendingFunctionHasBrace = (*aBuf_last_char == '{')) // Caller has ensured that aBuf is rtrim'd.
  977. {
  978. *aBuf_last_char = '\0'; // For the caller, remove it from further consideration.
  979. aBuf_last_char = aBuf + rtrim(aBuf, aBuf_last_char - aBuf) - 1; // Omit trailing whitespace too.
  980. }
  981. }
  982. return *aBuf_last_char == ')'; // This last check avoids detecting a label such as "Label(x):" as a function.
  983. // Also, it seems best never to allow if(...) to be a function call, even if it's blank inside such as if().
  984. // In addition, it seems best not to allow if(...) to ever be a function definition since such a function
  985. // could never be called as ACT_EXPRESSION since it would be seen as an IF-stmt instead.
  986. }
  987. ResultType Script::LoadIncludedFile(char *aFileSpec, bool aAllowDuplicateInclude, bool aIgnoreLoadFailure)
  988. // Returns OK or FAIL.
  989. // Below: Use double-colon as delimiter to set these apart from normal labels.
  990. // The main reason for this is that otherwise the user would have to worry
  991. // about a normal label being unintentionally valid as a hotkey, e.g.
  992. // "Shift:" might be a legitimate label that the user forgot is also
  993. // a valid hotkey:
  994. #define HOTKEY_FLAG "::"
  995. #define HOTKEY_FLAG_LENGTH 2
  996. {
  997. if (!aFileSpec || !*aFileSpec) return FAIL;
  998. #ifndef AUTOHOTKEYSC
  999. if (Line::sSourceFileCount >= Line::sMaxSourceFiles)
  1000. {
  1001. if (Line::sSourceFileCount >= ABSOLUTE_MAX_SOURCE_FILES)
  1002. return ScriptError("Too many includes."); // Short msg since so rare.
  1003. int new_max;
  1004. if (Line::sMaxSourceFiles)
  1005. {
  1006. new_max = 2*Line::sMaxSourceFiles;
  1007. if (new_max > ABSOLUTE_MAX_SOURCE_FILES)
  1008. new_max = ABSOLUTE_MAX_SOURCE_FILES;
  1009. }
  1010. else
  1011. new_max = 100;
  1012. // For simplicity and due to rarity of every needing to, expand by reallocating the array.
  1013. // Use a temp var. because realloc() returns NULL on failure but leaves original block allocated.
  1014. char **realloc_temp = (char **)realloc(Line::sSourceFile, new_max*sizeof(char *)); // If passed NULL, realloc() will do a malloc().
  1015. if (!realloc_temp)
  1016. return ScriptError(ERR_OUTOFMEM); // Short msg since so rare.
  1017. Line::sSourceFile = realloc_temp;
  1018. Line::sMaxSourceFiles = new_max;
  1019. }
  1020. char full_path[MAX_PATH];
  1021. #endif
  1022. // Keep this var on the stack due to recursion, which allows newly created lines to be given the
  1023. // correct file number even when some #include's have been encountered in the middle of the script:
  1024. int source_file_index = Line::sSourceFileCount;
  1025. if (!source_file_index)
  1026. // Since this is the first source file, it must be the main script file. Just point it to the
  1027. // location of the filespec already dynamically allocated:
  1028. Line::sSourceFile[source_file_index] = mFileSpec;
  1029. #ifndef AUTOHOTKEYSC // The "else" part below should never execute for compiled scripts since they never include anything (other than the main/combined script).
  1030. else
  1031. {
  1032. // Get the full path in case aFileSpec has a relative path. This is done so that duplicates
  1033. // can be reliably detected (we only want to avoid including a given file more than once):
  1034. char *filename_marker;
  1035. GetFullPathName(aFileSpec, sizeof(full_path), full_path, &filename_marker);
  1036. // Check if this file was already included. If so, it's not an error because we want
  1037. // to support automatic "include once" behavior. So just ignore repeats:
  1038. if (!aAllowDuplicateInclude)
  1039. for (int f = 0; f < source_file_index; ++f) // Here, source_file_index==Line::sSourceFileCount
  1040. if (!lstrcmpi(Line::sSourceFile[f], full_path)) // Case insensitive like the file system (testing shows that "Ä" == "ä" in the NTFS, which is hopefully how lstrcmpi works regardless of locale).
  1041. return OK;
  1042. // The file is added to the list further below, after the file has been opened, in case the
  1043. // opening fails and aIgnoreLoadFailure==true.
  1044. }
  1045. #endif
  1046. UCHAR *script_buf = NULL; // Init for the case when the buffer isn't used (non-standalone mode).
  1047. ULONG nDataSize = 0;
  1048. // <buf> should be no larger than LINE_SIZE because some later functions rely upon that:
  1049. char msg_text[MAX_PATH + 256], buf1[LINE_SIZE], buf2[LINE_SIZE], suffix[16], pending_function[LINE_SIZE] = "";
  1050. char *buf = buf1, *next_buf = buf2; // Oscillate between bufs to improve performance (avoids memcpy from buf2 to buf1).
  1051. size_t buf_length, next_buf_length, suffix_length;
  1052. bool pending_function_has_brace;
  1053. #ifndef AUTOHOTKEYSC
  1054. // Future: might be best to put a stat() or GetFileAttributes() in here for better handling.
  1055. FILE *fp = fopen(aFileSpec, "r");
  1056. if (!fp)
  1057. {
  1058. if (aIgnoreLoadFailure)
  1059. return OK;
  1060. snprintf(msg_text, sizeof(msg_text), "%s file \"%s\" cannot be opened."
  1061. , Line::sSourceFileCount > 0 ? "#Include" : "Script", aFileSpec);
  1062. MsgBox(msg_text);
  1063. return FAIL;
  1064. }
  1065. // v1.0.40.11: Otherwise, check if the first three bytes of the file are the UTF-8 BOM marker (and if
  1066. // so omit them from further consideration). Apps such as Notepad, WordPad, and Word all insert this
  1067. // marker if the file is saved in UTF-8 format. This omits such markers from both the main script and
  1068. // any files it includes via #Include.
  1069. // NOTE: To save code size, any UTF-8 BOM bytes at the beginning of a compiled script have already been
  1070. // stripped out by the script compiler. Thus, there is no need to check for them in the AUTOHOTKEYSC
  1071. // section further below.
  1072. if (fgets(buf, 4, fp)) // Success (the fourth character is the terminator).
  1073. {
  1074. if (strcmp(buf, "ďťż")) // UTF-8 BOM marker is NOT present.
  1075. rewind(fp); // Go back to the beginning so that the first three bytes aren't omitted during loading.
  1076. // The code size of rewind() has been checked and it seems very tiny.
  1077. }
  1078. //else file read error or EOF, let a later section handle it.
  1079. // This is done only after the file has been successfully opened in case aIgnoreLoadFailure==true:
  1080. if (source_file_index > 0)
  1081. Line::sSourceFile[source_file_index] = SimpleHeap::Malloc(full_path);
  1082. //else the first file was already taken care of by another means.
  1083. #else // Stand-alone mode (there are no include files in this mode since all of them were merged into the main script at the time of compiling).
  1084. HS_EXEArc_Read oRead;
  1085. // AutoIt3: Open the archive in this compiled exe.
  1086. // Jon gave me some details about why a password isn't needed: "The code in those libararies will
  1087. // only allow files to be extracted from the exe is is bound to (i.e the script that it was
  1088. // compiled with). There are various checks and CRCs to make sure that it can't be used to read
  1089. // the files from any other exe that is passed."
  1090. if (oRead.Open(aFileSpec, "") != HS_EXEARC_E_OK)
  1091. {
  1092. MsgBox(ERR_EXE_CORRUPTED, 0, aFileSpec); // Usually caused by virus corruption.
  1093. return FAIL;
  1094. }
  1095. // AutoIt3: Read the script (the func allocates the memory for the buffer :) )
  1096. if (oRead.FileExtractToMem(">AUTOHOTKEY SCRIPT<", &script_buf, &nDataSize) == HS_EXEARC_E_OK)
  1097. mCompiledHasCustomIcon = false;
  1098. else if (oRead.FileExtractToMem(">AHK WITH ICON<", &script_buf, &nDataSize) == HS_EXEARC_E_OK)
  1099. mCompiledHasCustomIcon = true;
  1100. else
  1101. {
  1102. oRead.Close(); // Close the archive
  1103. MsgBox("Could not extract script from EXE.", 0, aFileSpec);
  1104. return FAIL;
  1105. }
  1106. UCHAR *script_buf_marker = script_buf; // "marker" will track where we are in the mem. file as we read from it.
  1107. // Must cast to int to avoid loss of negative values:
  1108. #define SCRIPT_BUF_SPACE_REMAINING ((int)(nDataSize - (script_buf_marker - script_buf)))
  1109. int script_buf_space_remaining, max_chars_to_read; // script_buf_space_remaining must be an int to detect negatives.
  1110. // AutoIt3: We have the data in RAW BINARY FORM, the script is a text file, so
  1111. // this means that instead of a newline character, there may also be carridge
  1112. // returns 0x0d 0x0a (\r\n)
  1113. HS_EXEArc_Read *fp = &oRead; // To help consolidate the code below.
  1114. #endif
  1115. ++Line::sSourceFileCount;
  1116. // File is now open, read lines from it.
  1117. char *hotkey_flag, *cp, *cp1, *action_end, *hotstring_start, *hotstring_options;
  1118. Hotkey *hk;
  1119. LineNumberType pending_function_line_number, saved_line_number;
  1120. HookActionType hook_action;
  1121. bool is_label, suffix_has_tilde, in_comment_section, hotstring_options_all_valid;
  1122. // For the remap mechanism, e.g. a::b
  1123. int remap_stage;
  1124. vk_type remap_source_vk, remap_dest_vk = 0; // Only dest is initialized to enforce the fact that it is the flag/signal to indicate whether remapping is in progress.
  1125. char remap_source[32], remap_dest[32], remap_dest_modifiers[8]; // Must fit the longest key name (currently Browser_Favorites [17]), but buffer overflow is checked just in case.
  1126. char *extra_event;
  1127. bool remap_source_is_mouse, remap_dest_is_mouse, remap_keybd_to_mouse;
  1128. // For the line continuation mechanism:
  1129. bool do_ltrim, do_rtrim, literal_escapes, literal_derefs, literal_delimiters
  1130. , has_continuation_section, is_continuation_line;
  1131. #define CONTINUATION_SECTION_WITHOUT_COMMENTS 1 // MUST BE 1 because it's the default set by anything that's boolean-true.
  1132. #define CONTINUATION_SECTION_WITH_COMMENTS 2 // Zero means "not in a continuation section".
  1133. int in_continuation_section;
  1134. char *next_option, *option_end, orig_char, one_char_string[2], two_char_string[3]; // Line continuation mechanism's option parsing.
  1135. one_char_string[1] = '\0'; // Pre-terminate these to simplify code later below.
  1136. two_char_string[2] = '\0'; //
  1137. int continuation_line_count;
  1138. #define MAX_FUNC_VAR_EXCEPTIONS 2000
  1139. Var *func_exception_var[MAX_FUNC_VAR_EXCEPTIONS];
  1140. // Init both for main file and any included files loaded by this function:
  1141. mCurrFileIndex = source_file_index; // source_file_index is kept on the stack due to recursion (from #include).
  1142. #ifdef AUTOHOTKEYSC
  1143. // -1 (MAX_UINT in this case) to compensate for the fact that there is a comment containing
  1144. // the version number added to the top of each compiled script:
  1145. LineNumberType phys_line_number = -1;
  1146. // For compiled scripts, limit the number of characters to read to however many remain in the memory
  1147. // file or the size of the buffer, whichever is less.
  1148. script_buf_space_remaining = SCRIPT_BUF_SPACE_REMAINING; // Resolve macro only once, for performance.
  1149. max_chars_to_read = (LINE_SIZE - 1 < script_buf_space_remaining) ? LINE_SIZE - 1
  1150. : script_buf_space_remaining;
  1151. buf_length = GetLine(buf, max_chars_to_read, 0, script_buf_marker);
  1152. #else
  1153. LineNumberType phys_line_number = 0;
  1154. buf_length = GetLine(buf, LINE_SIZE - 1, 0, fp);
  1155. #endif
  1156. if (in_comment_section = !strncmp(buf, "/*", 2))
  1157. {
  1158. // Fixed for v1.0.35.08. Must reset buffer to allow a script's first line to be "/*".
  1159. *buf = '\0';
  1160. buf_length = 0;
  1161. }
  1162. while (buf_length != -1) // Compare directly to -1 since length is unsigned.
  1163. {
  1164. // For each whole line (a line with continuation section is counted as only a single line
  1165. // for the purpose of this outer loop).
  1166. // Keep track of this line's *physical* line number within its file for A_LineNumber and
  1167. // error reporting purposes. This must be done only in the outer loop so that it tracks
  1168. // the topmost line of any set of lines merged due to continuation section/line(s)..
  1169. mCombinedLineNumber = phys_line_number + 1;
  1170. // This must be reset for each iteration because a prior iteration may have changed it, even
  1171. // indirectly by calling something that changed it:
  1172. mCurrLine = NULL; // To signify that we're in transition, trying to load a new one.
  1173. // v1.0.44.13: An additional call to IsDirective() is now made up here so that #CommentFlag affects
  1174. // the line beneath it the same way as other lines (#EscapeChar et. al. didn't have this bug).
  1175. // It's best not to process ALL directives up here because then they would no longer support a
  1176. // continuation section beneath them (and possibly other drawbacks because it was never thoroughly
  1177. // tested).
  1178. if (!strnicmp(buf, "#CommentFlag", 12)) // Have IsDirective() process this now (it will also process it again later, which is harmless).
  1179. if (IsDirective(buf) == FAIL) // IsDirective() already displayed the error.
  1180. return CloseAndReturnFail(fp, script_buf);
  1181. // Read in the next line (if that next line is the start of a continuation secttion, append
  1182. // it to the line currently being processed:
  1183. for (has_continuation_section = false, in_continuation_section = 0;;)
  1184. {
  1185. // This increment relies on the fact that this loop always has at least one iteration:
  1186. ++phys_line_number; // Tracks phys. line number in *this* file (independent of any recursion caused by #Include).
  1187. #ifdef AUTOHOTKEYSC
  1188. // See similar section above for comments about the following:
  1189. script_buf_space_remaining = SCRIPT_BUF_SPACE_REMAINING; // Resolve macro only once, for performance.
  1190. max_chars_to_read = (LINE_SIZE - 1 < script_buf_space_remaining) ? LINE_SIZE - 1
  1191. : script_buf_space_remaining;
  1192. next_buf_length = GetLine(next_buf, max_chars_to_read, in_continuation_section, script_buf_marker);
  1193. #else
  1194. next_buf_length = GetLine(next_buf, LINE_SIZE - 1, in_continuation_section, fp);
  1195. #endif
  1196. if (next_buf_length && next_buf_length != -1) // Prevents infinite loop when file ends with an unclosed "/*" section. Compare directly to -1 since length is unsigned.
  1197. {
  1198. if (in_comment_section) // Look for the uncomment-flag.
  1199. {
  1200. if (!strncmp(next_buf, "*/", 2))
  1201. {
  1202. in_comment_section = false;
  1203. next_buf_length -= 2; // Adjust for removal of /* from the beginning of the string.
  1204. memmove(next_buf, next_buf + 2, next_buf_length + 1); // +1 to include the string terminator.
  1205. next_buf_length = ltrim(next_buf, next_buf_length); // Get rid of any whitespace that was between the comment-end and remaining text.
  1206. if (!*next_buf) // The rest of the line is empty, so it was just a naked comment-end.
  1207. continue;
  1208. }
  1209. else
  1210. continue;
  1211. }
  1212. else if (!in_continuation_section && !strncmp(next_buf, "/*", 2))
  1213. {
  1214. in_comment_section = true;
  1215. continue; // It's now commented out, so the rest of this line is ignored.
  1216. }
  1217. }
  1218. if (in_comment_section) // Above has incremented and read the next line, which is everything needed while inside /* .. */
  1219. {
  1220. if (next_buf_length == -1) // Compare directly to -1 since length is unsigned.
  1221. break; // By design, it's not an error. This allows "/*" to be used to comment out the bottommost portion of the script without needing a matching "*/".
  1222. // Otherwise, continue reading lines so that they can be merged with the line above them
  1223. // if they qualify as continuation lines.
  1224. continue;
  1225. }
  1226. if (!in_continuation_section) // This is either the first iteration or the line after the end of a previous continuation section.
  1227. {
  1228. // v1.0.38.06: The following has been fixed to exclude "(:" and "(::". These should be
  1229. // labels/hotkeys, not the start of a contination section. In addition, a line that starts
  1230. // with '(' but that ends with ':' should be treated as a label because labels such as
  1231. // "(label):" are far more common than something obscure like a continuation section whose
  1232. // join character is colon, namely "(Join:".
  1233. if ( !(in_continuation_section = (next_buf_length != -1 && *next_buf == '(' // Compare directly to -1 since length is unsigned.
  1234. && next_buf[1] != ':' && next_buf[next_buf_length - 1] != ':')) ) // Relies on short-circuit boolean order.
  1235. {
  1236. if (next_buf_length == -1) // Compare directly to -1 since length is unsigned.
  1237. break;
  1238. if (!next_buf_length)
  1239. // It is permitted to have blank lines and comment lines in between the line above
  1240. // and any continuation section/line that might come after the end of the
  1241. // comment/blank lines:
  1242. continue;
  1243. // SINCE ABOVE DIDN'T BREAK/CONTINUE, NEXT_BUF IS NON-BLANK.
  1244. if (next_buf[next_buf_length - 1] == ':' && *next_buf != ',')
  1245. // With the exception of lines starting with a comma, the last character of any
  1246. // legitimate continuation line can't be a colon because expressions can't end
  1247. // in a colon. The only exception is the ternary operator's colon, but that is
  1248. // very rare because it requires the line after it also be a continuation line
  1249. // or section, which is unusual to say the least -- so much so that it might be
  1250. // too obscure to even document as a known limitation. Anyway, by excluding lines
  1251. // that end with a colon from consideration ambiguity with normal labels
  1252. // and non-single-line hotkeys and hotstrings is eliminated.
  1253. break;
  1254. is_continuation_line = false; // Set default.
  1255. switch(toupper(*next_buf)) // Above has ensured *next_buf != '\0' (toupper might have problems with '\0').
  1256. {
  1257. case 'A': // "AND".
  1258. // See comments in the default section further below.
  1259. if (!strnicmp(next_buf, "and", 3) && IS_SPACE_OR_TAB_OR_NBSP(next_buf[3])) // Relies on short-circuit boolean order.
  1260. {
  1261. cp = omit_leading_whitespace(next_buf + 3);
  1262. // v1.0.38.06: The following was fixed to use EXPR_CORE vs. EXPR_OPERAND_TERMINATORS
  1263. // to properly detect a continuation line whose first char after AND/OR is "!~*&-+()":
  1264. if (!strchr(EXPR_CORE, *cp))
  1265. // This check recognizes the following examples as NON-continuation lines by checking
  1266. // that AND/OR aren't followed immediately by something that's obviously an operator:
  1267. // and := x, and = 2 (but not and += 2 since the an operand can have a unary plus/minus).
  1268. // This is done for backward compatibility. Also, it's documented that
  1269. // AND/OR/NOT aren't supported as variable names inside expressions.
  1270. is_continuation_line = true; // Override the default set earlier.
  1271. }
  1272. break;
  1273. case 'O': // "OR".
  1274. // See comments in the default section further below.
  1275. if (toupper(next_buf[1]) == 'R' && IS_SPACE_OR_TAB_OR_NBSP(next_buf[2])) // Relies on short-circuit boolean order.
  1276. {
  1277. cp = omit_leading_whitespace(next_buf + 2);
  1278. // v1.0.38.06: The following was fixed to use EXPR_CORE vs. EXPR_OPERAND_TERMINATORS
  1279. // to properly detect a continuation line whose first char after AND/OR is "!~*&-+()":
  1280. if (!strchr(EXPR_CORE, *cp)) // See comment in the "AND" case above.
  1281. is_continuation_line = true; // Override the default set earlier.
  1282. }
  1283. break;
  1284. default:
  1285. // Desired line continuation operators:
  1286. // Pretty much everything, namely:
  1287. // +, -, *, /, //, **, <<, >>, &, |, ^, <, >, <=, >=, =, ==, <>, !=, :=, +=, -=, /=, *=, ?, :
  1288. // And also the following remaining unaries (i.e. those that aren't also binaries): !, ~
  1289. // The first line below checks for ::, ++, and --. Those can't be continuation lines because:
  1290. // "::" isn't a valid operator (this also helps performance if there are many hotstrings).
  1291. // ++ and -- are ambiguous with an isolated line containing ++Var or --Var (and besides,
  1292. // wanting to use ++ to continue an expression seems extremely rare, though if there's ever
  1293. // demand for it, might be able to look at what lies to the right of the operator's operand
  1294. // -- though that would produce inconsisent continuation behavior since ++Var itself still
  1295. // could never be a continuation line due to ambiguity).
  1296. //
  1297. // The logic here isn't smart enough to differentiate between a leading ! or - that's
  1298. // meant as a continuation character and one that isn't. Even if it were, it would
  1299. // still be ambiguous in some cases because the author's intent isn't known; for example,
  1300. // the leading minus sign on the second line below is ambiguous, so will probably remain
  1301. // a continuation character in both v1 and v2:
  1302. // x := y
  1303. // -z ? a:=1 : func()
  1304. if ((*next_buf == ':' || *next_buf == '+' || *next_buf == '-') && next_buf[1] == *next_buf // See above.
  1305. || (*next_buf == '.' || *next_buf == '?') && !IS_SPACE_OR_TAB_OR_NBSP(next_buf[1]) // The "." and "?" operators require a space or tab after them to be legitimate. For ".", this is done in case period is ever a legal character in var names, such as struct support. For "?", it's done for backward compatibility since variable names can contain question marks (though "?" by itself is not considered a variable in v1.0.46).
  1306. && next_buf[1] != '=' // But allow ".=" (and "?=" too for code simplicity), since ".=" is the concat-assign operator.
  1307. || !strchr(CONTINUATION_LINE_SYMBOLS, *next_buf)) // Line doesn't start with a continuation char.
  1308. break; // Leave is_continuation_line set to its default of false.
  1309. // Some of the above checks must be done before the next ones.
  1310. if ( !(hotkey_flag = strstr(next_buf, HOTKEY_FLAG)) ) // Without any "::", it can't be a hotkey or hotstring.
  1311. {
  1312. is_continuation_line = true; // Override the default set earlier.
  1313. break;
  1314. }
  1315. if (*next_buf == ':') // First char is ':', so it's more likely a hotstring than a hotkey.
  1316. {
  1317. // Remember that hotstrings can contain what *appear* to be quoted literal strings,
  1318. // so detecting whether a "::" is in a quoted/literal string in this case would
  1319. // be more complicated. That's one reason this other method is used.
  1320. for (hotstring_options_all_valid = true, cp = next_buf + 1; *cp && *cp != ':'; ++cp)
  1321. if (!IS_HOTSTRING_OPTION(*cp)) // Not a perfect test, but eliminates most of what little remaining ambiguity exists between ':' as a continuation character vs. ':' as the start of a hotstring. It especially eliminates the ":=" operator.
  1322. {
  1323. hotstring_options_all_valid = false;
  1324. break;
  1325. }
  1326. if (hotstring_options_all_valid && *cp == ':') // It's almost certainly a hotstring.
  1327. break; // So don't treat it as a continuation line.
  1328. //else it's not a hotstring but it might still be a hotkey such as ": & x::".
  1329. // So continue checking below.
  1330. }
  1331. // Since above didn't "break", this line isn't a hotstring but it is probably a hotkey
  1332. // because above already discovered that it contains "::" somewhere. So try to find out
  1333. // if there's anything that disqualifies this from being a hotkey, such as some
  1334. // expression line that contains a quoted/literal "::" (or a line starting with
  1335. // a comma that contains an unquoted-but-literal "::" such as for FileAppend).
  1336. if (*next_buf == ',')
  1337. {
  1338. cp = omit_leading_whitespace(next_buf + 1);
  1339. // The above has set cp to the position of the non-whitespace item to the right of
  1340. // this comma. Normal (single-colon) labels can't contain commas, so only hotkey
  1341. // labels are sources of ambiguity. In addition, normal labels and hotstrings have
  1342. // already been checked for, higher above.
  1343. if ( strncmp(cp, HOTKEY_FLAG, HOTKEY_FLAG_LENGTH) // It's not a hotkey such as ",::action".
  1344. && strncmp(cp - 1, COMPOSITE_DELIMITER, COMPOSITE_DELIMITER_LENGTH) ) // ...and it's not a hotkey such as ", & y::action".
  1345. is_continuation_line = true; // Override the default set earlier.
  1346. }
  1347. else // First symbol in line isn't a comma but some other operator symbol.
  1348. {
  1349. // Check if the "::" found earlier appears to be inside a quoted/literal string.
  1350. // This check is NOT done for a line beginning with a comma since such lines
  1351. // can contain an unquoted-but-literal "::". In addition, this check is done this
  1352. // way to detect hotkeys such as the following:
  1353. // +keyname:: (and other hotkey modifier symbols such as ! and ^)
  1354. // +keyname1 & keyname2::
  1355. // +^:: (i.e. a modifier symbol followed by something that is a hotkey modifer and/or a hotkey suffix and/or an expression operator).
  1356. // <:: and &:: (i.e. hotkeys that are also expression-continuation symbols)
  1357. // By contrast, expressions that qualify as continuation lines can look like:
  1358. // . "xxx::yyy"
  1359. // + x . "xxx::yyy"
  1360. // In addition, hotkeys like the following should continue to be supported regardless
  1361. // of how things are done here:
  1362. // ^"::
  1363. // . & "::
  1364. // Finally, keep in mind that an expression-continuation line can start with two
  1365. // consecutive unary operators like !! or !*. It can also start with a double-symbol
  1366. // operator such as <=, <>, !=, &&, ||, //, **.
  1367. for (cp = next_buf; cp < hotkey_flag && *cp != '"'; ++cp);
  1368. if (cp == hotkey_flag) // No '"' found to left of "::", so this "::" appears to be a real hotkey flag rather than part of a literal string.
  1369. break; // Treat this line as a normal line vs. continuation line.
  1370. for (cp = hotkey_flag + HOTKEY_FLAG_LENGTH; *cp && *cp != '"'; ++cp);
  1371. if (*cp)
  1372. {
  1373. // Closing quote was found so "::" is probably inside a literal string of an
  1374. // expression (further checking seems unnecessary given the fairly extreme
  1375. // rarity of using '"' as a key in a hotkey definition).
  1376. is_continuation_line = true; // Override the default set earlier.
  1377. }
  1378. //else no closing '"' found, so this "::" probably belongs to something like +":: or
  1379. // . & "::. Treat this line as a normal line vs. continuation line.
  1380. }
  1381. } // switch(toupper(*next_buf))
  1382. if (is_continuation_line)
  1383. {
  1384. if (buf_length + next_buf_length >= LINE_SIZE - 1) // -1 to account for the extra space added below.
  1385. {
  1386. ScriptError(ERR_CONTINUATION_SECTION_TOO_LONG, next_buf);
  1387. return CloseAndReturnFail(fp, script_buf);
  1388. }
  1389. if (*next_buf != ',') // Insert space before expression operators so that built/combined expression works correctly (some operators like 'and', 'or', '.', and '?' currently require spaces on either side) and also for readability of ListLines.
  1390. buf[buf_length++] = ' ';
  1391. memcpy(buf + buf_length, next_buf, next_buf_length + 1); // Append this line to prev. and include the zero terminator.
  1392. buf_length += next_buf_length;
  1393. continue; // Check for yet more continuation lines after this one.
  1394. }
  1395. // Since above didn't continue, there is no continuation line or section. In addition,
  1396. // since this line isn't blank, no further searching is needed.
  1397. break;
  1398. } // if (!in_continuation_section)
  1399. // OTHERWISE in_continuation_section != 0, so the above has found the first line of a new
  1400. // continuation section.
  1401. // "has_continuation_section" indicates whether the line we're about to construct is partially
  1402. // composed of continuation lines beneath it. It's separate from continuation_line_count
  1403. // in case there is another continuation section immediately after/adjacent to the first one,
  1404. // but the second one doesn't have any lines in it:
  1405. has_continuation_section = true;
  1406. continuation_line_count = 0; // Reset for this new section.
  1407. // Otherwise, parse options. First set the defaults, which can be individually overridden
  1408. // by any options actually present. RTrim defaults to ON for two reasons:
  1409. // 1) Whitespace often winds up at the end of a lines in a text editor by accident. In addition,
  1410. // whitespace at the end of any consolidated/merged line will be rtrim'd anyway, since that's
  1411. // how command parsing works.
  1412. // 2) Copy & paste from the forum and perhaps other web sites leaves a space at the end of each
  1413. // line. Although this behavior is probably site/browser-specific, it's a consideration.
  1414. do_ltrim = g_ContinuationLTrim; // Start off at global default.
  1415. do_rtrim = true; // Seems best to rtrim even if this line is a hotstring, since it is very rare that trailing spaces and tabs would ever be desirable.
  1416. // For hotstrings (which could be detected via *buf==':'), it seems best not to default the
  1417. // escape character (`) to be literal because the ability to have `t `r and `n inside the
  1418. // hotstring continuation section seems more useful/common than the ability to use the
  1419. // accent character by itself literally (which seems quite rare in most languages).
  1420. literal_escapes = false;
  1421. literal_derefs = false;
  1422. literal_delimiters = true; // This is the default even for hotstrings because although using (*buf != ':') would improve loading performance, it's not a 100% reliable way to detect hotstrings.
  1423. // The default is linefeed because:
  1424. // 1) It's the best choice for hotstrings, for which the line continuation mechanism is well suited.
  1425. // 2) It's good for FileAppend.
  1426. // 3) Minor: Saves memory in large sections by being only one character instead of two.
  1427. suffix[0] = '\n';
  1428. suffix[1] = '\0';
  1429. suffix_length = 1;
  1430. for (next_option = omit_leading_whitespace(next_buf + 1); *next_option; next_option = omit_leading_whitespace(option_end))
  1431. {
  1432. // Find the end of this option item:
  1433. if ( !(option_end = StrChrAny(next_option, " \t")) ) // Space or tab.
  1434. option_end = next_option + strlen(next_option); // Set to position of zero terminator instead.
  1435. // Temporarily terminate to help eliminate ambiguity for words contained inside other words,
  1436. // such as hypothetical "Checked" inside of "CheckedGray":
  1437. orig_char = *option_end;
  1438. *option_end = '\0';
  1439. if (!strnicmp(next_option, "Join", 4))
  1440. {
  1441. next_option += 4;
  1442. strlcpy(suffix, next_option, sizeof(suffix)); // The word "Join" by itself will product an empty string, as documented.
  1443. // Passing true for the last parameter supports `s as the special escape character,
  1444. // which allows space to be used by itself and also at the beginning or end of a string
  1445. // containing other chars.
  1446. ConvertEscapeSequences(suffix, g_EscapeChar, true);
  1447. suffix_length = strlen(suffix);
  1448. }
  1449. else if (!strnicmp(next_option, "LTrim", 5))
  1450. do_ltrim = (next_option[5] != '0'); // i.e. Only an explicit zero will turn it off.
  1451. else if (!strnicmp(next_option, "RTrim", 5))
  1452. do_rtrim = (next_option[5] != '0');
  1453. else
  1454. {
  1455. // Fix for v1.0.36.01: Missing "else" above, because otherwise, the option Join`r`n
  1456. // would be processed above but also be processed again below, this time seeing the
  1457. // accent and thinking it's the signal to treat accents literally for the entire
  1458. // continuation section rather than as escape characters.
  1459. // Within this terminated option substring, allow the characters to be adjacent to
  1460. // improve usability:
  1461. for (; *next_option; ++next_option)
  1462. {
  1463. switch (*next_option)
  1464. {
  1465. case '`': // Although not using g_EscapeChar (reduces code size/complexity), #EscapeChar is still supported by continuation sections; it's just that enabling the option uses '`' rather than the custom escape-char (one reason is that that custom escape-char might be ambiguous with future/past options if it's somehing weird like an alphabetic character).
  1466. literal_escapes = true;
  1467. break;
  1468. case '%': // Same comment as above.
  1469. literal_derefs = true;
  1470. break;
  1471. case ',': // Same comment as above.
  1472. literal_delimiters = false;
  1473. break;
  1474. case 'C': // v1.0.45.03: For simplicity, anything that begins with "C" is enough to
  1475. case 'c': // identify it as the option to allow comments in the section.
  1476. in_continuation_section = CONTINUATION_SECTION_WITH_COMMENTS; // Override the default, which is boolean true (i.e. 1).
  1477. break;
  1478. }
  1479. }
  1480. }
  1481. // If the item was not handled by the above, ignore it because it is unknown.
  1482. *option_end = orig_char; // Undo the temporary termination.
  1483. } // for() each item in option list
  1484. continue; // Now that the open-parenthesis of this continuation section has been processed, proceed to the next line.
  1485. } // if (!in_continuation_section)
  1486. // Since above didn't "continue", we're in the continuation section and thus next_buf contains
  1487. // either a line to be appended onto buf or the closing parenthesis of this continuation section.
  1488. if (next_buf_length == -1) // Compare directly to -1 since length is unsigned.
  1489. {
  1490. ScriptError(ERR_MISSING_CLOSE_PAREN, buf);
  1491. return CloseAndReturnFail(fp, script_buf);
  1492. }
  1493. if (next_buf_length == -2) // v1.0.45.03: Special flag that means "this is a commented-out line to be
  1494. continue; // entirely omitted from the continuation section." Compare directly to -2 since length is unsigned.
  1495. if (*next_buf == ')')
  1496. {
  1497. in_continuation_section = 0; // Facilitates back-to-back continuation sections and proper incrementing of phys_line_number.
  1498. next_buf_length = rtrim(next_buf); // Done because GetLine() wouldn't have done it due to have told it we're in a continuation section.
  1499. // Anything that lies to the right of the close-parenthesis gets appended verbatim, with
  1500. // no trimming (for flexibility) and no options-driven translation:
  1501. cp = next_buf + 1; // Use temp var cp to avoid altering next_buf (for maintainability).
  1502. --next_buf_length; // This is now the length of cp, not next_buf.
  1503. }
  1504. else
  1505. {
  1506. cp = next_buf;
  1507. // The following are done in this block only because anything that comes after the closing
  1508. // parenthesis (i.e. the block above) is exempt from translations and custom trimming.
  1509. // This means that commas are always delimiters and percent signs are always deref symbols
  1510. // in the previous block.
  1511. if (do_rtrim)
  1512. next_buf_length = rtrim(next_buf, next_buf_length);
  1513. if (do_ltrim)
  1514. next_buf_length = ltrim(next_buf, next_buf_length);
  1515. // Escape each comma and percent sign in the body of the continuation section so that
  1516. // the later parsing stages will see them as literals. Although, it's not always
  1517. // necessary to do this (e.g. commas in the last parameter of a command don't need to
  1518. // be escaped, nor do percent signs in hotstrings' auto-replace text), the settings
  1519. // are applied unconditionally because:
  1520. // 1) Determining when its safe to omit the translation would add a lot of code size and complexity.
  1521. // 2) The translation doesn't affect the functionality of the script since escaped literals
  1522. // are always de-escaped at a later stage, at least for everything that's likely to matter
  1523. // or that's reasonable to put into a continuation section (e.g. a hotstring's replacement text).
  1524. // UPDATE for v1.0.44.11: #EscapeChar, #DerefChar, #Delimiter are now supported by continuation
  1525. // sections because there were some requests for that in forum.
  1526. int replacement_count = 0;
  1527. if (literal_escapes) // literal_escapes must be done FIRST because otherwise it would also replace any accents added for literal_delimiters or literal_derefs.
  1528. {
  1529. one_char_string[0] = g_EscapeChar; // These strings were terminated earlier, so no need to
  1530. two_char_string[0] = g_EscapeChar; // do it here. In addition, these strings must be set by
  1531. two_char_string[1] = g_EscapeChar; // each iteration because the #EscapeChar (and similar directives) can occur multiple times, anywhere in the script.
  1532. replacement_count += StrReplace(next_buf, one_char_string, two_char_string, SCS_SENSITIVE, UINT_MAX, LINE_SIZE);
  1533. }
  1534. if (literal_derefs)
  1535. {
  1536. one_char_string[0] = g_DerefChar;
  1537. two_char_string[0] = g_EscapeChar;
  1538. two_char_string[1] = g_DerefChar;
  1539. replacement_count += StrReplace(next_buf, one_char_string, two_char_string, SCS_SENSITIVE, UINT_MAX, LINE_SIZE);
  1540. }
  1541. if (literal_delimiters)
  1542. {
  1543. one_char_string[0] = g_delimiter;
  1544. two_char_string[0] = g_EscapeChar;
  1545. two_char_string[1] = g_delimiter;
  1546. replacement_count += StrReplace(next_buf, one_char_string, two_char_string, SCS_SENSITIVE, UINT_MAX, LINE_SIZE);
  1547. }
  1548. if (replacement_count) // Update the length if any actual replacements were done.
  1549. next_buf_length = strlen(next_buf);
  1550. } // Handling of a normal line within a continuation section.
  1551. // Must check the combined length only after anything that might have expanded the string above.
  1552. if (buf_length + next_buf_length + suffix_length >= LINE_SIZE)
  1553. {
  1554. ScriptError(ERR_CONTINUATION_SECTION_TOO_LONG, cp);
  1555. return CloseAndReturnFail(fp, script_buf);
  1556. }
  1557. ++continuation_line_count;
  1558. // Append this continuation line onto the primary line.
  1559. // The suffix for the previous line gets written immediately prior writing this next line,
  1560. // which allows the suffix to be omitted for the final line. But if this is the first line,
  1561. // No suffix is written because there is no previous line in the continuation section.
  1562. // In addition, cp!=next_buf, this is the special line whose text occurs to the right of the
  1563. // continuation section's closing parenthesis. In this case too, the previous line doesn't
  1564. // get a suffix.
  1565. if (continuation_line_count > 1 && suffix_length && cp == next_buf)
  1566. {
  1567. memcpy(buf + buf_length, suffix, suffix_length + 1); // Append and include the zero terminator.
  1568. buf_length += suffix_length; // Must be done only after the old value of buf_length was used above.
  1569. }
  1570. if (next_buf_length)
  1571. {
  1572. memcpy(buf + buf_length, cp, next_buf_length + 1); // Append this line to prev. and include the zero terminator.
  1573. buf_length += next_buf_length; // Must be done only after the old value of buf_length was used above.
  1574. }
  1575. } // for() each sub-line (continued line) that composes this line.
  1576. // buf_length can't be -1 (though next_buf_length can) because outer loop's condition prevents it:
  1577. if (!buf_length) // Done only after the line number increments above so that the physical line number is properly tracked.
  1578. goto continue_main_loop; // In lieu of "continue", for performance.
  1579. // Since neither of the above executed, or they did but didn't "continue",
  1580. // buf now contains a non-commented line, either by itself or built from
  1581. // any continuation sections/lines that might have been present. Also note that
  1582. // by design, phys_line_number will be greater than mCombinedLineNumber whenever
  1583. // a continuation section/lines were used to build this combined line.
  1584. // If there's a previous line waiting to be processed, its fate can now be determined based on the
  1585. // nature of *this* line:
  1586. if (*pending_function)
  1587. {
  1588. // Somewhat messy to decrement then increment later, but it's probably easier than the
  1589. // alternatives due to the use of "continue" in some places above. NOTE: phys_line_number
  1590. // would not need to be decremented+incremented even if the below resulted in a recursive
  1591. // call to us (though it doesn't currently) because line_number's only purpose is to
  1592. // remember where this layer left off when the recursion collapses back to us.
  1593. // Fix for v1.0.31.05: It's not enough just to decrement mCombinedLineNumber because there
  1594. // might be some blank lines or commented-out lines between this function call/definition
  1595. // and the line that follows it, each of which will have previously incremented mCombinedLineNumber.
  1596. saved_line_number = mCombinedLineNumber;
  1597. mCombinedLineNumber = pending_function_line_number; // Done so that any syntax errors that occur during the calls below will report the correct line number.
  1598. // Open brace means this is a function definition. NOTE: buf was already ltrimmed by GetLine().
  1599. // Could use *g_act[ACT_BLOCK_BEGIN].Name instead of '{', but it seems too elaborate to be worth it.
  1600. if (*buf == '{' || pending_function_has_brace) // v1.0.41: Support one-true-brace, e.g. fn(...) {
  1601. {
  1602. // Note that two consecutive function definitions aren't possible:
  1603. // fn1()
  1604. // fn2()
  1605. // {
  1606. // ...
  1607. // }
  1608. // In the above, the first would automatically be deemed a function call by means of
  1609. // the check higher above (by virtue of the fact that the line after it isn't an open-brace).
  1610. if (g->CurrentFunc)
  1611. {
  1612. // Though it might be allowed in the future -- perhaps to have nested functions have
  1613. // access to their parent functions' local variables, or perhaps just to improve
  1614. // script readability and maintainability -- it's currently not allowed because of
  1615. // the practice of maintaining the func_exception_var list on our stack:
  1616. ScriptError("Functions cannot contain functions.", pending_function);
  1617. return CloseAndReturnFail(fp, script_buf);
  1618. }
  1619. if (!DefineFunc(pending_function, func_exception_var))
  1620. return CloseAndReturnFail(fp, script_buf);
  1621. if (pending_function_has_brace) // v1.0.41: Support one-true-brace for function def, e.g. fn() {
  1622. if (!AddLine(ACT_BLOCK_BEGIN))
  1623. return CloseAndReturnFail(fp, script_buf);
  1624. }
  1625. else // It's a function call on a line by itself, such as fn(x). It can't be if(..) because another section checked that.
  1626. {
  1627. if (!ParseAndAddLine(pending_function, ACT_EXPRESSION))
  1628. return CloseAndReturnFail(fp, script_buf);
  1629. mCurrLine = NULL; // Prevents showing misleading vicinity lines if the line after a function call is a syntax error.
  1630. }
  1631. mCombinedLineNumber = saved_line_number;
  1632. *pending_function = '\0'; // Reset now that it's been fully handled, as an indicator for subsequent iterations.
  1633. // Now fall through to the below so that *this* line (the one after it) will be processed.
  1634. // Note that this line might be a pre-processor directive, label, etc. that won't actually
  1635. // become a runtime line per se.
  1636. } // if (*pending_function)
  1637. // By doing the following section prior to checking for hotkey and hotstring labels, double colons do
  1638. // not need to be escaped inside naked function calls and function definitions such as the following:
  1639. // fn("::") ; Function call.
  1640. // fn(Str="::") ; Function definition with default value for its parameter.
  1641. if (IsFunction(buf, &pending_function_has_brace)) // If true, it's either a function definition or a function call (to be distinguished later).
  1642. {
  1643. // Defer this line until the next line comes in, which helps determine whether this line is
  1644. // a function call vs. definition:
  1645. strcpy(pending_function, buf);
  1646. pending_function_line_number = mCombinedLineNumber;
  1647. goto continue_main_loop; // In lieu of "continue", for performance.
  1648. }
  1649. // The following "examine_line" label skips the following parts above:
  1650. // 1) IsFunction() because that's only for a function call or definition alone on a line
  1651. // e.g. not "if fn()" or x := fn(). Those who goto this label don't need that processing.
  1652. // 2) The "if (*pending_function)" block: Doesn't seem applicable for the callers of this label.
  1653. // 3) The inner loop that handles continuation sections: Not needed by the callers of this label.
  1654. // 4) Things like the following should be skipped because callers of this label don't want the
  1655. // physical line number changed (which would throw off the count of lines that lie beneath a remap):
  1656. // mCombinedLineNumber = phys_line_number + 1;
  1657. // ++phys_line_number;
  1658. // 5) "mCurrLine = NULL": Probably not necessary since it's only for error reporting. Worst thing
  1659. // that could happen is that syntax errors would be thrown off, which testing shows isn't the case.
  1660. examine_line:
  1661. // "::" alone isn't a hotstring, it's a label whose name is colon.
  1662. // Below relies on the fact that no valid hotkey can start with a colon, since
  1663. // ": & somekey" is not valid (since colon is a shifted key) and colon itself
  1664. // should instead be defined as "+;::". It also relies on short-circuit boolean:
  1665. hotstring_start = NULL;
  1666. hotstring_options = NULL; // Set default as "no options were specified for this hotstring".
  1667. hotkey_flag = NULL;
  1668. if (buf[0] == ':' && buf[1])
  1669. {
  1670. if (buf[1] != ':')
  1671. {
  1672. hotstring_options = buf + 1; // Point it to the hotstring's option letters.
  1673. // The following relies on the fact that options should never contain a literal colon.
  1674. // ALSO, the following doesn't use IS_HOTSTRING_OPTION() for backward compatibility,
  1675. // performance, and because it seems seldom if ever necessary at this late a stage.
  1676. if ( !(hotstring_start = strchr(hotstring_options, ':')) )
  1677. hotstring_start = NULL; // Indicate that this isn't a hotstring after all.
  1678. else
  1679. ++hotstring_start; // Points to the hotstring itself.
  1680. }
  1681. else // Double-colon, so it's a hotstring if there's more after this (but this means no options are present).
  1682. if (buf[2])
  1683. hotstring_start = buf + 2; // And leave hotstring_options at its default of NULL to indicate no options.
  1684. //else it's just a naked "::", which is considered to be an ordinary label whose name is colon.
  1685. }
  1686. if (hotstring_start)
  1687. {
  1688. // Find the hotstring's final double-colon by considering escape sequences from left to right.
  1689. // This is necessary for to handles cases such as the following:
  1690. // ::abc```::::Replacement String
  1691. // The above hotstring translates literally into "abc`::".
  1692. char *escaped_double_colon = NULL;
  1693. for (cp = hotstring_start; ; ++cp) // Increment to skip over the symbol just found by the inner for().
  1694. {
  1695. for (; *cp && *cp != g_EscapeChar && *cp != ':'; ++cp); // Find the next escape char or colon.
  1696. if (!*cp) // end of string.
  1697. break;
  1698. cp1 = cp + 1;
  1699. if (*cp == ':')
  1700. {
  1701. if (*cp1 == ':') // Found a non-escaped double-colon, so this is the right one.
  1702. {
  1703. hotkey_flag = cp++; // Increment to have loop skip over both colons.
  1704. // and the continue with the loop so that escape sequences in the replacement
  1705. // text (if there is replacement text) are also translated.
  1706. }
  1707. // else just a single colon, or the second colon of an escaped pair (`::), so continue.
  1708. continue;
  1709. }
  1710. switch (*cp1)
  1711. {
  1712. // Only lowercase is recognized for these:
  1713. case 'a': *cp1 = '\a'; break; // alert (bell) character
  1714. case 'b': *cp1 = '\b'; break; // backspace
  1715. case 'f': *cp1 = '\f'; break; // formfeed
  1716. case 'n': *cp1 = '\n'; break; // newline
  1717. case 'r': *cp1 = '\r'; break; // carriage return
  1718. case 't': *cp1 = '\t'; break; // horizontal tab
  1719. case 'v': *cp1 = '\v'; break; // vertical tab
  1720. // Otherwise, if it's not one of the above, the escape-char is considered to
  1721. // mark the next character as literal, regardless of what it is. Examples:
  1722. // `` -> `
  1723. // `:: -> :: (effectively)
  1724. // `; -> ;
  1725. // `c -> c (i.e. unknown escape sequences resolve to the char after the `)
  1726. }
  1727. // Below has a final +1 to include the terminator:
  1728. MoveMemory(cp, cp1, strlen(cp1) + 1);
  1729. // Since single colons normally do not need to be escaped, this increments one extra
  1730. // for double-colons to skip over the entire pair so that its second colon
  1731. // is not seen as part of the hotstring's final double-colon. Example:
  1732. // ::ahc```::::Replacement String
  1733. if (*cp == ':' && *cp1 == ':')
  1734. ++cp;
  1735. } // for()
  1736. if (!hotkey_flag)
  1737. hotstring_start = NULL; // Indicate that this isn't a hotstring after all.
  1738. }
  1739. if (!hotstring_start) // Not a hotstring (hotstring_start is checked *again* in case above block changed it; otherwise hotkeys like ": & x" aren't recognized).
  1740. {
  1741. // Note that there may be an action following the HOTKEY_FLAG (on the same line).
  1742. if (hotkey_flag = strstr(buf, HOTKEY_FLAG)) // Find the first one from the left, in case there's more than 1.
  1743. {
  1744. if (hotkey_flag == buf && hotkey_flag[2] == ':') // v1.0.46: Support ":::" to mean "colon is a hotkey".
  1745. ++hotkey_flag;
  1746. // v1.0.40: It appears to be a hotkey, but validate it as such before committing to processing
  1747. // it as a hotkey. If it fails validation as a hotkey, treat it as a command that just happens
  1748. // to contain a double-colon somewhere. This avoids the need to escape double colons in scripts.
  1749. // Note: Hotstrings can't suffer from this type of ambiguity because a leading colon or pair of
  1750. // colons makes them easier to detect.
  1751. cp = omit_trailing_whitespace(buf, hotkey_flag); // For maintainability.
  1752. orig_char = *cp;
  1753. *cp = '\0'; // Temporarily terminate.
  1754. if (!Hotkey::TextInterpret(omit_leading_whitespace(buf), NULL, false)) // Passing NULL calls it in validate-only mode.
  1755. hotkey_flag = NULL; // It's not a valid hotkey, so indicate that it's a command (i.e. one that contains a literal double-colon, which avoids the need to escape the double-colon).
  1756. *cp = orig_char; // Undo the temp. termination above.
  1757. }
  1758. }
  1759. // Treat a naked "::" as a normal label whose label name is colon:
  1760. if (is_label = (hotkey_flag && hotkey_flag > buf)) // It's a hotkey/hotstring label.
  1761. {
  1762. if (g->CurrentFunc)
  1763. {
  1764. // Even if it weren't for the reasons below, the first hotkey/hotstring label in a script
  1765. // will end the auto-execute section with a "return". Therefore, if this restriction here
  1766. // is ever removed, be sure that that extra return doesn't get put inside the function.
  1767. //
  1768. // The reason for not allowing hotkeys and hotstrings inside a function's body is that
  1769. // when the subroutine is launched, the hotstring/hotkey would be using the function's
  1770. // local variables. But that is not appropriate and it's likely to cause problems even
  1771. // if it were. It doesn't seem useful in any case. By contrast, normal labels can
  1772. // safely exist inside a function body and since the body is a block, other validation
  1773. // ensures that a Gosub or Goto can't jump to it from outside the function.
  1774. ScriptError("Hotkeys/hotstrings are not allowed inside functions.", buf);
  1775. return CloseAndReturnFail(fp, script_buf);
  1776. }
  1777. if (mLastLine && mLastLine->mActionType == ACT_IFWINACTIVE)
  1778. {
  1779. mCurrLine = mLastLine; // To show vicinity lines.
  1780. ScriptError("IfWin should be #IfWin.", buf);
  1781. return CloseAndReturnFail(fp, script_buf);
  1782. }
  1783. *hotkey_flag = '\0'; // Terminate so that buf is now the label itself.
  1784. hotkey_flag += HOTKEY_FLAG_LENGTH; // Now hotkey_flag is the hotkey's action, if any.
  1785. if (!hotstring_start)
  1786. {
  1787. ltrim(hotkey_flag); // Has already been rtrimmed by GetLine().
  1788. rtrim(buf); // Trim the new substring inside of buf (due to temp termination). It has already been ltrimmed.
  1789. cp = hotkey_flag; // Set default, conditionally overridden below (v1.0.44.07).
  1790. // v1.0.40: Check if this is a remap rather than hotkey:
  1791. if ( *hotkey_flag // This hotkey's action is on the same line as its label.
  1792. && (remap_source_vk = TextToVK(cp1 = Hotkey::TextToModifiers(buf, NULL)))
  1793. && (remap_dest_vk = hotkey_flag[1] ? TextToVK(cp = Hotkey::TextToModifiers(hotkey_flag, NULL)) : 0xFF) ) // And the action appears to be a remap destination rather than a command.
  1794. // For above:
  1795. // Fix for v1.0.44.07: Set remap_dest_vk to 0xFF if hotkey_flag's length is only 1 because:
  1796. // 1) It allows a destination key that doesn't exist in the keyboard layout (such as 6::đ in
  1797. // English).
  1798. // 2) It improves performance a little by not calling TextToVK except when the destination key
  1799. // might be a mouse button or some longer key name whose actual/correct VK value is relied
  1800. // upon by other places below.
  1801. // Fix for v1.0.40.01: Since remap_dest_vk is also used as the flag to indicate whether
  1802. // this line qualifies as a remap, must do it last in the statement above. Otherwise,
  1803. // the statement might short-circuit and leave remap_dest_vk as non-zero even though
  1804. // the line shouldn't be a remap. For example, I think a hotkey such as "x & y::return"
  1805. // would trigger such a bug.
  1806. {
  1807. // These will be ignored in other stages if it turns out not to be a remap later below:
  1808. remap_source_is_mouse = IsMouseVK(remap_source_vk);
  1809. remap_dest_is_mouse = IsMouseVK(remap_dest_vk);
  1810. remap_keybd_to_mouse = !remap_source_is_mouse && remap_dest_is_mouse;
  1811. snprintf(remap_source, sizeof(remap_source), "%s%s"
  1812. , strlen(cp1) == 1 && IsCharUpper(*cp1) ? "+" : "" // Allow A::b to be different than a::b.
  1813. , buf); // Include any modifiers too, e.g. ^b::c.
  1814. strlcpy(remap_dest, cp, sizeof(remap_dest)); // But exclude modifiers here; they're wanted separately.
  1815. strlcpy(remap_dest_modifiers, hotkey_flag, sizeof(remap_dest_modifiers));
  1816. if (cp - hotkey_flag < sizeof(remap_dest_modifiers)) // Avoid reading beyond the end.
  1817. remap_dest_modifiers[cp - hotkey_flag] = '\0'; // Terminate at the proper end of the modifier string.
  1818. remap_stage = 0; // Init for use in the next stage.
  1819. // In the unlikely event that the dest key has the same name as a command, disqualify it
  1820. // from being a remap (as documented). v1.0.40.05: If the destination key has any modifiers,
  1821. // it is unambiguously a key name rather than a command, so the switch() isn't necessary.
  1822. if (*remap_dest_modifiers)
  1823. goto continue_main_loop; // It will see that remap_dest_vk is non-zero and act accordingly.
  1824. switch (remap_dest_vk)
  1825. {
  1826. case VK_CONTROL: // Checked in case it was specified as "Control" rather than "Ctrl".
  1827. case VK_SLEEP:
  1828. if (StrChrAny(hotkey_flag, " \t,")) // Not using g_delimiter (reduces code size/complexity).
  1829. break; // Any space, tab, or enter means this is a command rather than a remap destination.
  1830. goto continue_main_loop; // It will see that remap_dest_vk is non-zero and act accordingly.
  1831. // "Return" and "Pause" as destination keys are always considered commands instead.
  1832. // This is documented and is done to preserve backward compatibility.
  1833. case VK_RETURN:
  1834. // v1.0.40.05: Although "Return" can't be a destination, "Enter" can be. Must compare
  1835. // to "Return" not "Enter" so that things like "vk0d" (the VK of "Enter") can also be a
  1836. // destination key:
  1837. if (!stricmp(remap_dest, "Return"))
  1838. break;
  1839. goto continue_main_loop; // It will see that remap_dest_vk is non-zero and act accordingly.
  1840. case VK_PAUSE: // Used for both "Pause" and "Break"
  1841. break;
  1842. default: // All other VKs are valid destinations and thus the remap is valid.
  1843. goto continue_main_loop; // It will see that remap_dest_vk is non-zero and act accordingly.
  1844. }
  1845. // Since above didn't goto, indicate that this is not a remap after all:
  1846. remap_dest_vk = 0;
  1847. }
  1848. }
  1849. // else don't trim hotstrings since literal spaces in both substrings are significant.
  1850. // If this is the first hotkey label encountered, Add a return before
  1851. // adding the label, so that the auto-exectute section is terminated.
  1852. // Only do this if the label is a hotkey because, for example,
  1853. // the user may want to fully execute a normal script that contains
  1854. // no hotkeys but does contain normal labels to which the execution
  1855. // should fall through, if specified, rather than returning.
  1856. // But this might result in weirdness? Example:
  1857. //testlabel:
  1858. // Sleep, 1
  1859. // return
  1860. // ^a::
  1861. // return
  1862. // It would put the hard return in between, which is wrong. But in the case above,
  1863. // the first sub shouldn't have a return unless there's a part up top that ends in Exit.
  1864. // So if Exit is encountered before the first hotkey, don't add the return?
  1865. // Even though wrong, the return is harmless because it's never executed? Except when
  1866. // falling through from above into a hotkey (which probably isn't very valid anyway)?
  1867. // Update: Below must check if there are any true hotkey labels, not just regular labels.
  1868. // Otherwise, a normal (non-hotkey) label in the autoexecute section would count and
  1869. // thus the RETURN would never be added here, even though it should be:
  1870. // Notes about the below macro:
  1871. // Fix for v1.0.34: Don't point labels to this particular RETURN so that labels
  1872. // can point to the very first hotkey or hotstring in a script. For example:
  1873. // Goto Test
  1874. // Test:
  1875. // ^!z::ToolTip Without the fix`, this is never displayed by "Goto Test".
  1876. // UCHAR_MAX signals it not to point any pending labels to this RETURN.
  1877. // mCurrLine = NULL -> signifies that we're in transition, trying to load a new one.
  1878. #define CHECK_mNoHotkeyLabels \
  1879. if (mNoHotkeyLabels)\
  1880. {\
  1881. mNoHotkeyLabels = false;\
  1882. if (!AddLine(ACT_RETURN, NULL, UCHAR_MAX))\
  1883. return CloseAndReturnFail(fp, script_buf);\
  1884. mCurrLine = NULL;\
  1885. }
  1886. CHECK_mNoHotkeyLabels
  1887. // For hotstrings, the below makes the label include leading colon(s) and the full option
  1888. // string (if any) so that the uniqueness of labels is preserved. For example, we want
  1889. // the following two hotstring labels to be unique rather than considered duplicates:
  1890. // ::abc::
  1891. // :c:abc::
  1892. if (!AddLabel(buf, true)) // Always add a label before adding the first line of its section.
  1893. return CloseAndReturnFail(fp, script_buf);
  1894. hook_action = 0; // Set default.
  1895. if (*hotkey_flag) // This hotkey's action is on the same line as its label.
  1896. {
  1897. if (!hotstring_start)
  1898. // Don't add the alt-tabs as a line, since it has no meaning as a script command.
  1899. // But do put in the Return regardless, in case this label is ever jumped to
  1900. // via Goto/Gosub:
  1901. if ( !(hook_action = Hotkey::ConvertAltTab(hotkey_flag, false)) )
  1902. if (!ParseAndAddLine(hotkey_flag, IsFunction(hotkey_flag) ? ACT_EXPRESSION : ACT_INVALID)) // It can't be a function definition vs. call since it's a single-line hotkey.
  1903. return CloseAndReturnFail(fp, script_buf);
  1904. // Also add a Return that's implicit for a single-line hotkey. This is also
  1905. // done for auto-replace hotstrings in case gosub/goto is ever used to jump
  1906. // to their labels:
  1907. if (!AddLine(ACT_RETURN))
  1908. return CloseAndReturnFail(fp, script_buf);
  1909. }
  1910. if (hotstring_start)
  1911. {
  1912. if (!*hotstring_start)
  1913. {
  1914. // The following error message won't indicate the correct line number because
  1915. // the hotstring (as a label) does not actually exist as a line. But it seems
  1916. // best to report it this way in case the hotstring is inside a #Include file,
  1917. // so that the correct file name and approximate line number are shown:
  1918. ScriptError("This hotstring is missing its abbreviation.", buf); // Display buf vs. hotkey_flag in case the line is simply "::::".
  1919. return CloseAndReturnFail(fp, script_buf);
  1920. }
  1921. // In the case of hotstrings, hotstring_start is the beginning of the hotstring itself,
  1922. // i.e. the character after the second colon. hotstring_options is NULL if no options,
  1923. // otherwise it's the first character in the options list (option string is not terminated,
  1924. // but instead ends in a colon). hotkey_flag is blank if it's not an auto-replace
  1925. // hotstring, otherwise it contains the auto-replace text.
  1926. // v1.0.42: Unlike hotkeys, duplicate hotstrings are not detected. This is because
  1927. // hotstrings are less commonly used and also because it requires more code to find
  1928. // hotstring duplicates (and performs a lot worse if a script has thousands of
  1929. // hotstrings) because of all the hotstring options.
  1930. if (!Hotstring::AddHotstring(mLastLabel, hotstring_options ? hotstring_options : ""
  1931. , hotstring_start, hotkey_flag, has_continuation_section))
  1932. return CloseAndReturnFail(fp, script_buf);
  1933. }
  1934. else // It's a hotkey vs. hotstring.
  1935. {
  1936. if (hk = Hotkey::FindHotkeyByTrueNature(buf, suffix_has_tilde)) // Parent hotkey found. Add a child/variant hotkey for it.
  1937. {
  1938. if (hook_action) // suffix_has_tilde has always been ignored for these types (alt-tab hotkeys).
  1939. {
  1940. // Hotkey::Dynamic() contains logic and comments similar to this, so maintain them together.
  1941. // An attempt to add an alt-tab variant to an existing hotkey. This might have
  1942. // merit if the intention is to make it alt-tab now but to later disable that alt-tab
  1943. // aspect via the Hotkey cmd to let the context-sensitive variants shine through
  1944. // (take effect).
  1945. hk->mHookAction = hook_action;
  1946. }
  1947. else
  1948. {
  1949. // Detect duplicate hotkey variants to help spot bugs in scripts.
  1950. if (hk->FindVariant()) // See if there's already a variant matching the current criteria (suffix_has_tilde does not make variants distinct form each other because it would require firing two hotkey IDs in response to pressing one hotkey, which currently isn't in the design).
  1951. {
  1952. mCurrLine = NULL; // Prevents showing unhelpful vicinity lines.
  1953. ScriptError("Duplicate hotkey.", buf);
  1954. return CloseAndReturnFail(fp, script_buf);
  1955. }
  1956. if (!hk->AddVariant(mLastLabel, suffix_has_tilde))
  1957. {
  1958. ScriptError(ERR_OUTOFMEM, buf);
  1959. return CloseAndReturnFail(fp, script_buf);
  1960. }
  1961. }
  1962. }
  1963. else // No parent hotkey yet, so create it.
  1964. if ( !(hk = Hotkey::AddHotkey(mLastLabel, hook_action, NULL, suffix_has_tilde, false)) )
  1965. return CloseAndReturnFail(fp, script_buf); // It already displayed the error.
  1966. }
  1967. goto continue_main_loop; // In lieu of "continue", for performance.
  1968. } // if (is_label = ...)
  1969. // Otherwise, not a hotkey or hotstring. Check if it's a generic, non-hotkey label:
  1970. if (buf[buf_length - 1] == ':') // Labels must end in a colon (buf was previously rtrimmed).
  1971. {
  1972. if (buf_length == 1) // v1.0.41.01: Properly handle the fact that this line consists of only a colon.
  1973. {
  1974. ScriptError(ERR_UNRECOGNIZED_ACTION, buf);
  1975. return CloseAndReturnFail(fp, script_buf);
  1976. }
  1977. // Labels (except hotkeys) must contain no whitespace, delimiters, or escape-chars.
  1978. // This is to avoid problems where a legitimate action-line ends in a colon,
  1979. // such as "WinActivate SomeTitle" and "#Include c:".
  1980. // We allow hotkeys to violate this since they may contain commas, and since a normal
  1981. // script line (i.e. just a plain command) is unlikely to ever end in a double-colon:
  1982. for (cp = buf, is_label = true; *cp; ++cp)
  1983. if (IS_SPACE_OR_TAB(*cp) || *cp == g_delimiter || *cp == g_EscapeChar)
  1984. {
  1985. is_label = false;
  1986. break;
  1987. }
  1988. if (is_label) // It's a generic, non-hotkey/non-hotstring label.
  1989. {
  1990. // v1.0.44.04: Fixed this check by moving it after the above loop.
  1991. // Above has ensured buf_length>1, so it's safe to check for double-colon:
  1992. // v1.0.44.03: Don't allow anything that ends in "::" (other than a line consisting only
  1993. // of "::") to be a normal label. Assume it's a command instead (if it actually isn't, a
  1994. // later stage will report it as "invalid hotkey"). This change avoids the situation in
  1995. // which a hotkey like ^!ä:: is seen as invalid because the current keyboard layout doesn't
  1996. // have a "ä" key. Without this change, if such a hotkey appears at the top of the script,
  1997. // its subroutine would execute immediately as a normal label, which would be especially
  1998. // bad if the hotkey were something like the "Shutdown" command.
  1999. if (buf[buf_length - 2] == ':' && buf_length > 2) // i.e. allow "::" as a normal label, but consider anything else with double-colon to be a failed-hotkey label that terminates the auto-exec section.
  2000. {
  2001. CHECK_mNoHotkeyLabels // Terminate the auto-execute section since this is a failed hotkey vs. a mere normal label.
  2002. snprintf(msg_text, sizeof(msg_text), "Note: The hotkey %s will not be active because it does not exist in the current keyboard layout.", buf);
  2003. MsgBox(msg_text);
  2004. }
  2005. buf[--buf_length] = '\0'; // Remove the trailing colon.
  2006. rtrim(buf, buf_length); // Has already been ltrimmed.
  2007. if (!AddLabel(buf, false))
  2008. return CloseAndReturnFail(fp, script_buf);
  2009. goto continue_main_loop; // In lieu of "continue", for performance.
  2010. }
  2011. }
  2012. // Since above didn't "goto", it's not a label.
  2013. if (*buf == '#')
  2014. {
  2015. saved_line_number = mCombinedLineNumber; // Backup in case IsDirective() processes an include file, which would change mCombinedLineNumber's value.
  2016. switch(IsDirective(buf)) // Note that it may alter the contents of buf, at least in the case of #IfWin.
  2017. {
  2018. case CONDITION_TRUE:
  2019. // Since the directive may have been a #include which called us recursively,
  2020. // restore the class's values for these two, which are maintained separately
  2021. // like this to avoid having to specify them in various calls, especially the
  2022. // hundreds of calls to ScriptError() and LineError():
  2023. mCurrFileIndex = source_file_index;
  2024. mCombinedLineNumber = saved_line_number;
  2025. goto continue_main_loop; // In lieu of "continue", for performance.
  2026. case FAIL: // IsDirective() already displayed the error.
  2027. return CloseAndReturnFail(fp, script_buf);
  2028. //case CONDITION_FALSE: Do nothing; let processing below handle it.
  2029. }
  2030. }
  2031. // Otherwise, treat it as a normal script line.
  2032. // v1.0.41: Support the "} else {" style in one-true-brace (OTB). As a side-effect,
  2033. // any command, not just an else, is probably supported to the right of '}', not just "else".
  2034. // This is undocumented because it would make for less readable scripts, and doesn't seem
  2035. // to have much value.
  2036. if (*buf == '}')
  2037. {
  2038. if (!AddLine(ACT_BLOCK_END))
  2039. return CloseAndReturnFail(fp, script_buf);
  2040. // The following allows the next stage to see "else" or "else {" if it's present:
  2041. if ( !*(buf = omit_leading_whitespace(buf + 1)) )
  2042. goto continue_main_loop; // It's just a naked "}", so no more processing needed for this line.
  2043. buf_length = strlen(buf); // Update for possible use below.
  2044. }
  2045. // First do a little special handling to support actions on the same line as their
  2046. // ELSE, e.g.:
  2047. // else if x = 1
  2048. // This is done here rather than in ParseAndAddLine() because it's fairly
  2049. // complicated to do there (already tried it) mostly due to the fact that
  2050. // literal_map has to be properly passed in a recursive call to itself, as well
  2051. // as properly detecting special commands that don't have keywords such as
  2052. // IF comparisons, ACT_ASSIGN, +=, -=, etc.
  2053. // v1.0.41: '{' was added to the line below to support no spaces inside "}else{".
  2054. if (!(action_end = StrChrAny(buf, "\t ,{"))) // Position of first tab/space/comma/open-brace. For simplicitly, a non-standard g_delimiter is not supported.
  2055. action_end = buf + buf_length; // It's done this way so that ELSE can be fully handled here; i.e. that ELSE does not have to be in the list of commands recognizable by ParseAndAddLine().
  2056. // The following method ensures that words or variables that start with "Else", e.g. ElseAction, are not
  2057. // incorrectly detected as an Else command:
  2058. if (strlicmp(buf, "Else", (UINT)(action_end - buf))) // It's not an ELSE. ("Else" is used vs. g_act[ACT_ELSE].Name for performance).
  2059. {
  2060. // It's not an ELSE. Also, at this stage it can't be ACT_EXPRESSION (such as an isolated function call)
  2061. // because it would have been already handled higher above.
  2062. // v1.0.41.01: Check if there is a command/action on the same line as the '{'. This is apparently
  2063. // a style that some people use, and it also supports "{}" as a shorthand way of writing an empty block.
  2064. if (*buf == '{')
  2065. {
  2066. if (!AddLine(ACT_BLOCK_BEGIN))
  2067. return CloseAndReturnFail(fp, script_buf);
  2068. if ( *(action_end = omit_leading_whitespace(buf + 1)) ) // There is an action to the right of the '{'.
  2069. {
  2070. mCurrLine = NULL; // To signify that we're in transition, trying to load a new one.
  2071. if (!ParseAndAddLine(action_end, IsFunction(action_end) ? ACT_EXPRESSION : ACT_INVALID)) // If it's a function, it must be a call vs. a definition because a function can't be defined on the same line as an open-brace.
  2072. return CloseAndReturnFail(fp, script_buf);
  2073. }
  2074. // Otherwise, there was either no same-line action or the same-line action was successfully added,
  2075. // so do nothing.
  2076. }
  2077. else
  2078. if (!ParseAndAddLine(buf))
  2079. return CloseAndReturnFail(fp, script_buf);
  2080. }
  2081. else // This line is an ELSE, possibly with another command immediately after it (on the same line).
  2082. {
  2083. // Add the ELSE directly rather than calling ParseAndAddLine() because that function
  2084. // would resolve escape sequences throughout the entire length of <buf>, which we
  2085. // don't want because we wouldn't have access to the corresponding literal-map to
  2086. // figure out the proper use of escaped characters:
  2087. if (!AddLine(ACT_ELSE))
  2088. return CloseAndReturnFail(fp, script_buf);
  2089. mCurrLine = NULL; // To signify that we're in transition, trying to load a new one.
  2090. action_end = omit_leading_whitespace(action_end); // Now action_end is the word after the ELSE.
  2091. if (*action_end == g_delimiter) // Allow "else, action"
  2092. action_end = omit_leading_whitespace(action_end + 1);
  2093. if (*action_end && !ParseAndAddLine(action_end, IsFunction(action_end) ? ACT_EXPRESSION : ACT_INVALID)) // If it's a function, it must be a call vs. a definition because a function can't be defined on the same line as an Else.
  2094. return CloseAndReturnFail(fp, script_buf);
  2095. // Otherwise, there was either no same-line action or the same-line action was successfully added,
  2096. // so do nothing.
  2097. }
  2098. continue_main_loop: // This method is used in lieu of "continue" for performance and code size reduction.
  2099. if (remap_dest_vk)
  2100. {
  2101. // For remapping, decided to use a "macro expansion" approach because I think it's considerably
  2102. // smaller in code size and complexity than other approaches would be. I originally wanted to
  2103. // do it with the hook by changing the incoming event prior to passing it back out again (for
  2104. // example, a::b would transform an incoming 'a' keystroke into 'b' directly without having
  2105. // to suppress the original keystroke and simulate a new one). Unfortunately, the low-level
  2106. // hooks apparently do not allow this. Here is the test that confirmed it:
  2107. // if (event.vkCode == 'A')
  2108. // {
  2109. // event.vkCode = 'B';
  2110. // event.scanCode = 0x30; // Or use vk_to_sc(event.vkCode).
  2111. // return CallNextHookEx(g_KeybdHook, aCode, wParam, lParam);
  2112. // }
  2113. switch (++remap_stage)
  2114. {
  2115. case 1: // Stage 1: Add key-down hotkey label, e.g. *LButton::
  2116. buf_length = sprintf(buf, "*%s::", remap_source); // Should be no risk of buffer overflow due to prior validation.
  2117. goto examine_line; // Have the main loop process the contents of "buf" as though it came in from the script.
  2118. case 2: // Stage 2.
  2119. // Copied into a writable buffer for maintainability: AddLine() might rely on this.
  2120. // Also, it seems unnecessary to set press-duration to -1 even though the auto-exec section might
  2121. // have set it to something higher than -1 because:
  2122. // 1) Press-duration doesn't apply to normal remappings since they use down-only and up-only events.
  2123. // 2) Although it does apply to remappings such as a::B and a::^b (due to press-duration being
  2124. // applied after a change to modifier state), those remappings are fairly rare and supporting
  2125. // a non-negative-one press-duration (almost always 0) probably adds a degree of flexibility
  2126. // that may be desirable to keep.
  2127. // 3) SendInput may become the predominant SendMode, so press-duration won't often be in effect anyway.
  2128. // 4) It has been documented that remappings use the auto-execute section's press-duration.
  2129. strcpy(buf, "-1"); // Does NOT need to be "-1, -1" for SetKeyDelay (see above).
  2130. // The primary reason for adding Key/MouseDelay -1 is to minimize the chance that a one of
  2131. // these hotkey threads will get buried under some other thread such as a timer, which
  2132. // would disrupt the remapping if #MaxThreadsPerHotkey is at its default of 1.
  2133. AddLine(remap_dest_is_mouse ? ACT_SETMOUSEDELAY : ACT_SETKEYDELAY, &buf, 1, NULL); // PressDuration doesn't need to be specified because it doesn't affect down-only and up-only events.
  2134. if (remap_keybd_to_mouse)
  2135. {
  2136. // Since source is keybd and dest is mouse, prevent keyboard auto-repeat from auto-repeating
  2137. // the mouse button (since that would be undesirable 90% of the time). This is done
  2138. // by inserting a single extra IF-statement above the Send that produces the down-event:
  2139. buf_length = sprintf(buf, "if not GetKeyState(\"%s\")", remap_dest); // Should be no risk of buffer overflow due to prior validation.
  2140. remap_stage = 9; // Have it hit special stage 9+1 next time for code reduction purposes.
  2141. goto examine_line; // Have the main loop process the contents of "buf" as though it came in from the script.
  2142. }
  2143. // Otherwise, remap_keybd_to_mouse==false, so fall through to next case.
  2144. case 10:
  2145. extra_event = ""; // Set default.
  2146. switch (remap_dest_vk)
  2147. {
  2148. case VK_LMENU:
  2149. case VK_RMENU:
  2150. case VK_MENU:
  2151. switch (remap_source_vk)
  2152. {
  2153. case VK_LCONTROL:
  2154. case VK_CONTROL:
  2155. extra_event = "{LCtrl up}"; // Somewhat surprisingly, this is enough to make "Ctrl::Alt" properly remap both right and left control.
  2156. break;
  2157. case VK_RCONTROL:
  2158. extra_event = "{RCtrl up}";
  2159. break;
  2160. // Below is commented out because its only purpose was to allow a shift key remapped to alt
  2161. // to be able to alt-tab. But that wouldn't work correctly due to the need for the following
  2162. // hotkey, which does more harm than good by impacting the normal Alt key's ability to alt-tab
  2163. // (if the normal Alt key isn't remapped): *Tab::Send {Blind}{Tab}
  2164. //case VK_LSHIFT:
  2165. //case VK_SHIFT:
  2166. // extra_event = "{LShift up}";
  2167. // break;
  2168. //case VK_RSHIFT:
  2169. // extra_event = "{RShift up}";
  2170. // break;
  2171. }
  2172. break;
  2173. }
  2174. mCurrLine = NULL; // v1.0.40.04: Prevents showing misleading vicinity lines for a syntax-error such as %::%
  2175. sprintf(buf, "{Blind}%s%s{%s DownTemp}", extra_event, remap_dest_modifiers, remap_dest); // v1.0.44.05: DownTemp vs. Down. See Send's DownTemp handler for details.
  2176. if (!AddLine(ACT_SEND, &buf, 1, NULL)) // v1.0.40.04: Check for failure due to bad remaps such as %::%.
  2177. return CloseAndReturnFail(fp, script_buf);
  2178. AddLine(ACT_RETURN);
  2179. // Add key-up hotkey label, e.g. *LButton up::
  2180. buf_length = sprintf(buf, "*%s up::", remap_source); // Should be no risk of buffer overflow due to prior validation.
  2181. remap_stage = 2; // Adjust to hit stage 3 next time (in case this is stage 10).
  2182. goto examine_line; // Have the main loop process the contents of "buf" as though it came in from the script.
  2183. case 3: // Stage 3.
  2184. strcpy(buf, "-1");
  2185. AddLine(remap_dest_is_mouse ? ACT_SETMOUSEDELAY : ACT_SETKEYDELAY, &buf, 1, NULL);
  2186. sprintf(buf, "{Blind}{%s Up}", remap_dest); // Unlike the down-event above, remap_dest_modifiers is not included for the up-event; e.g. ^{b up} is inappropriate.
  2187. AddLine(ACT_SEND, &buf, 1, NULL);
  2188. AddLine(ACT_RETURN);
  2189. remap_dest_vk = 0; // Reset to signal that the remapping expansion is now complete.
  2190. break; // Fall through to the next section so that script loading can resume at the next line.
  2191. }
  2192. } // if (remap_dest_vk)
  2193. // Since above didn't "continue", resume loading script line by line:
  2194. buf = next_buf;
  2195. buf_length = next_buf_length;
  2196. next_buf = (buf == buf1) ? buf2 : buf1;
  2197. // The line above alternates buffers (toggles next_buf to be the unused buffer), which helps
  2198. // performance because it avoids memcpy from buf2 to buf1.
  2199. } // for each whole/constructed line.
  2200. if (*pending_function) // Since this is the last non-comment line, the pending function must be a function call, not a function definition.
  2201. {
  2202. // Somewhat messy to decrement then increment later, but it's probably easier than the
  2203. // alternatives due to the use of "continue" in some places above.
  2204. saved_line_number = mCombinedLineNumber;
  2205. mCombinedLineNumber = pending_function_line_number; // Done so that any syntax errors that occur during the calls below will report the correct line number.
  2206. if (!ParseAndAddLine(pending_function, ACT_EXPRESSION)) // Must be function call vs. definition since otherwise the above would have detected the opening brace beneath it and already cleared pending_function.
  2207. return CloseAndReturnFail(fp, script_buf);
  2208. mCombinedLineNumber = saved_line_number;
  2209. }
  2210. #ifdef AUTOHOTKEYSC
  2211. free(script_buf); // AutoIt3: Close the archive and free the file in memory.
  2212. oRead.Close(); //
  2213. #else
  2214. fclose(fp);
  2215. #endif
  2216. return OK;
  2217. }
  2218. // Small inline to make LoadIncludedFile() code cleaner.
  2219. #ifdef AUTOHOTKEYSC
  2220. inline ResultType Script::CloseAndReturnFailFunc(HS_EXEArc_Read *fp, UCHAR *aBuf)
  2221. {
  2222. free(aBuf);
  2223. fp->Close();
  2224. return FAIL;
  2225. }
  2226. #else
  2227. inline ResultType Script::CloseAndReturnFailFunc(FILE *fp)
  2228. {
  2229. fclose(fp);
  2230. return FAIL;
  2231. }
  2232. #endif
  2233. #ifdef AUTOHOTKEYSC
  2234. size_t Script::GetLine(char *aBuf, int aMaxCharsToRead, int aInContinuationSection, UCHAR *&aMemFile) // last param = reference to pointer
  2235. #else
  2236. size_t Script::GetLine(char *aBuf, int aMaxCharsToRead, int aInContinuationSection, FILE *fp)
  2237. #endif
  2238. {
  2239. size_t aBuf_length = 0;
  2240. #ifdef AUTOHOTKEYSC
  2241. if (!aBuf || !aMemFile) return -1;
  2242. if (aMaxCharsToRead < 1) return -1; // We're signaling to caller that the end of the memory file has been reached.
  2243. // Otherwise, continue reading characters from the memory file until either a newline is
  2244. // reached or aMaxCharsToRead have been read:
  2245. // Track "i" separately from aBuf_length because we want to read beyond the bounds of the memory file.
  2246. int i;
  2247. for (i = 0; i < aMaxCharsToRead; ++i)
  2248. {
  2249. if (aMemFile[i] == '\n')
  2250. {
  2251. // The end of this line has been reached. Don't copy this char into the target buffer.
  2252. // In addition, if the previous char was '\r', remove it from the target buffer:
  2253. if (aBuf_length > 0 && aBuf[aBuf_length - 1] == '\r')
  2254. aBuf[--aBuf_length] = '\0';
  2255. ++i; // i.e. so that aMemFile will be adjusted to omit this newline char.
  2256. break;
  2257. }
  2258. else
  2259. aBuf[aBuf_length++] = aMemFile[i];
  2260. }
  2261. // We either read aMaxCharsToRead or reached the end of the line (as indicated by the newline char).
  2262. // In the former case, aMemFile might now be changed to be a position outside the bounds of the
  2263. // memory area, which the caller will reflect back to us during the next call as a 0 value for
  2264. // aMaxCharsToRead, which we then signal to the caller (above) as the end of the file):
  2265. aMemFile += i; // Update this value for use by the caller.
  2266. // Terminate the buffer (the caller has already ensured that there's room for the terminator
  2267. // via its value of aMaxCharsToRead):
  2268. aBuf[aBuf_length] = '\0';
  2269. #else
  2270. if (!aBuf || !fp) return -1;
  2271. if (aMaxCharsToRead < 1) return 0;
  2272. if (feof(fp)) return -1; // Previous call to this function probably already read the last line.
  2273. if (fgets(aBuf, aMaxCharsToRead, fp) == NULL) // end-of-file or error
  2274. {
  2275. *aBuf = '\0'; // Reset since on error, contents added by fgets() are indeterminate.
  2276. return -1;
  2277. }
  2278. aBuf_length = strlen(aBuf);
  2279. if (!aBuf_length)
  2280. return 0;
  2281. if (aBuf[aBuf_length-1] == '\n')
  2282. aBuf[--aBuf_length] = '\0';
  2283. if (aBuf[aBuf_length-1] == '\r') // In case there are any, e.g. a Macintosh or Unix file?
  2284. aBuf[--aBuf_length] = '\0';
  2285. #endif
  2286. if (aInContinuationSection)
  2287. {
  2288. char *cp = omit_leading_whitespace(aBuf);
  2289. if (aInContinuationSection == CONTINUATION_SECTION_WITHOUT_COMMENTS) // By default, continuation sections don't allow comments (lines beginning with a semicolon are treated as literal text).
  2290. {
  2291. // Caller relies on us to detect the end of the continuation section so that trimming
  2292. // will be done on the final line of the section and so that a comment can immediately
  2293. // follow the closing parenthesis (on the same line). Example:
  2294. // (
  2295. // Text
  2296. // ) ; Same line comment.
  2297. if (*cp != ')') // This isn't the last line of the continuation section, so leave the line untrimmed (caller will apply the ltrim setting on its own).
  2298. return aBuf_length; // Earlier sections are responsible for keeping aBufLength up-to-date with any changes to aBuf.
  2299. //else this line starts with ')', so continue on to later section that checks for a same-line comment on its right side.
  2300. }
  2301. else // aInContinuationSection == CONTINUATION_SECTION_WITH_COMMENTS (i.e. comments are allowed in this continuation section).
  2302. {
  2303. // Fix for v1.0.46.09+: The "com" option shouldn't put "ltrim" into effect.
  2304. if (!strncmp(cp, g_CommentFlag, g_CommentFlagLength)) // Case sensitive.
  2305. {
  2306. *aBuf = '\0'; // Since this line is a comment, have the caller ignore it.
  2307. return -2; // Callers tolerate -2 only when in a continuation section. -2 indicates, "don't include this line at all, not even as a blank line to which the JOIN string (default "\n") will apply.
  2308. }
  2309. if (*cp == ')') // This isn't the last line of the continuation section, so leave the line untrimmed (caller will apply the ltrim setting on its own).
  2310. {
  2311. ltrim(aBuf); // Ltrim this line unconditionally so that caller will see that it starts with ')' without having to do extra steps.
  2312. aBuf_length = strlen(aBuf); // ltrim() doesn't always return an accurate length, so do it this way.
  2313. }
  2314. }
  2315. }
  2316. // Since above didn't return, either:
  2317. // 1) We're not in a continuation section at all, so apply ltrim() to support semicolons after tabs or
  2318. // other whitespace. Seems best to rtrim also.
  2319. // 2) CONTINUATION_SECTION_WITHOUT_COMMENTS but this line is the final line of the section. Apply
  2320. // trim() and other logic further below because caller might rely on it.
  2321. // 3) CONTINUATION_SECTION_WITH_COMMENTS (i.e. comments allowed), but this line isn't a comment (though
  2322. // it may start with ')' and thus be the final line of this section). In either case, need to check
  2323. // for same-line comments further below.
  2324. if (aInContinuationSection != CONTINUATION_SECTION_WITH_COMMENTS) // Case #1 & #2 above.
  2325. {
  2326. aBuf_length = trim(aBuf);
  2327. if (!strncmp(aBuf, g_CommentFlag, g_CommentFlagLength)) // Case sensitive.
  2328. {
  2329. // Due to other checks, aInContinuationSection==false whenever the above condition is true.
  2330. *aBuf = '\0';
  2331. return 0;
  2332. }
  2333. }
  2334. //else CONTINUATION_SECTION_WITH_COMMENTS (case #3 above), which due to other checking also means that
  2335. // this line isn't a comment (though it might have a comment on its right side, which is checked below).
  2336. // CONTINUATION_SECTION_WITHOUT_COMMENTS would already have returned higher above if this line isn't
  2337. // the last line of the continuation section.
  2338. if (g_AllowSameLineComments)
  2339. {
  2340. // Handle comment-flags that appear to the right of a valid line. But don't
  2341. // allow these types of comments if the script is considers to be the AutoIt2
  2342. // style, to improve compatibility with old scripts that may use non-escaped
  2343. // comment-flags as literal characters rather than comments:
  2344. char *cp, *prevp;
  2345. for (cp = strstr(aBuf, g_CommentFlag); cp; cp = strstr(cp + g_CommentFlagLength, g_CommentFlag))
  2346. {
  2347. // If no whitespace to its left, it's not a valid comment.
  2348. // We insist on this so that a semi-colon (for example) immediately after
  2349. // a word (as semi-colons are often used) will not be considered a comment.
  2350. prevp = cp - 1;
  2351. if (prevp < aBuf) // should never happen because we already checked above.
  2352. {
  2353. *aBuf = '\0';
  2354. return 0;
  2355. }
  2356. if (IS_SPACE_OR_TAB_OR_NBSP(*prevp)) // consider it to be a valid comment flag
  2357. {
  2358. *prevp = '\0';
  2359. aBuf_length = rtrim_with_nbsp(aBuf, prevp - aBuf); // Since it's our responsibility to return a fully trimmed string.
  2360. break; // Once the first valid comment-flag is found, nothing after it can matter.
  2361. }
  2362. else // No whitespace to the left.
  2363. if (*prevp == g_EscapeChar) // Remove the escape char.
  2364. {
  2365. // The following isn't exactly correct because it prevents an include filename from ever
  2366. // containing the literal string "`;". This is because attempts to escape the accent via
  2367. // "``;" are not supported. This is documented here as a known limitation because fixing
  2368. // it would probably break existing scripts that rely on the fact that accents do not need
  2369. // to be escaped inside #Include. Also, the likelihood of "`;" appearing literally in a
  2370. // legitimate #Include file seems vanishingly small.
  2371. memmove(prevp, prevp + 1, strlen(prevp + 1) + 1); // +1 for the terminator.
  2372. --aBuf_length;
  2373. // Then continue looking for others.
  2374. }
  2375. // else there wasn't any whitespace to its left, so keep looking in case there's
  2376. // another further on in the line.
  2377. } // for()
  2378. } // if (g_AllowSameLineComments)
  2379. return aBuf_length; // The above is responsible for keeping aBufLength up-to-date with any changes to aBuf.
  2380. }
  2381. inline ResultType Script::IsDirective(char *aBuf)
  2382. // aBuf must be a modifiable string since this function modifies it in the case of "#Include %A_ScriptDir%"
  2383. // changes it. It must also be large enough to accept the replacement of %A_ScriptDir% with a larger string.
  2384. // Returns CONDITION_TRUE, CONDITION_FALSE, or FAIL.
  2385. // Note: Don't assume that every line in the script that starts with '#' is a directive
  2386. // because hotkeys can legitimately start with that as well. i.e., the following line should
  2387. // not be unconditionally ignored, just because it starts with '#', since it is a valid hotkey:
  2388. // #y::run, notepad
  2389. {
  2390. char end_flags[] = {' ', '\t', g_delimiter, '\0'}; // '\0' must be last.
  2391. char *directive_end, *parameter_raw;
  2392. if ( !(directive_end = StrChrAny(aBuf, end_flags)) )
  2393. {
  2394. directive_end = aBuf + strlen(aBuf); // Point it to the zero terminator.
  2395. parameter_raw = NULL;
  2396. }
  2397. else
  2398. if (!*(parameter_raw = omit_leading_whitespace(directive_end)))
  2399. parameter_raw = NULL;
  2400. // The raw parameter retains any leading comma for those directives that need that (none currently).
  2401. // But the following omits that comma:
  2402. char *parameter;
  2403. if (!parameter_raw)
  2404. parameter = NULL;
  2405. else // Since parameter_raw is non-NULL, it's also non-blank and non-whitespace due to the above checking.
  2406. if (*parameter_raw != g_delimiter)
  2407. parameter = parameter_raw;
  2408. else // It's a delimiter, so "parameter" will be whatever non-whitespace character follows it, if any.
  2409. if (!*(parameter = omit_leading_whitespace(parameter_raw + 1)))
  2410. parameter = NULL;
  2411. //else leave it set to the value returned by omit_leading_whitespace().
  2412. int value; // Helps detect values that are too large, since some of the target globals are UCHAR.
  2413. // Use strnicmp() so that a match is found as long as aBuf starts with the string in question.
  2414. // e.g. so that "#SingleInstance, on" will still work too, but
  2415. // "#a::run, something, "#SingleInstance" (i.e. a hotkey) will not be falsely detected
  2416. // due to using a more lenient function such as strcasestr().
  2417. // UPDATE: Using strlicmp() now so that overlapping names, such as #MaxThreads and #MaxThreadsPerHotkey,
  2418. // won't get mixed up:
  2419. #define IS_DIRECTIVE_MATCH(directive) (!strlicmp(aBuf, directive, directive_name_length))
  2420. UINT directive_name_length = (UINT)(directive_end - aBuf); // To avoid calculating it every time in the macro above.
  2421. bool is_include_again = false; // Set default in case of short-circuit boolean.
  2422. if (IS_DIRECTIVE_MATCH("#Include") || (is_include_again = IS_DIRECTIVE_MATCH("#IncludeAgain")))
  2423. {
  2424. // Standalone EXEs ignore this directive since the included files were already merged in
  2425. // with the main file when the script was compiled. These should have been removed
  2426. // or commented out by Ahk2Exe, but just in case, it's safest to ignore them:
  2427. #ifdef AUTOHOTKEYSC
  2428. return CONDITION_TRUE;
  2429. #else
  2430. // If the below decision is ever changed, be sure to update ahk2exe with the same change:
  2431. // "parameter" is checked rather than parameter_raw for backward compatibility with earlier versions,
  2432. // in which a leading comma is not considered part of the filename. Although this behavior is incorrect
  2433. // because it prevents files whose names start with a comma from being included without the first
  2434. // delim-comma being there too, it is kept because filesnames that start with a comma seem
  2435. // exceedingly rare. As a workaround, the script can do #Include ,,FilenameWithLeadingComma.ahk
  2436. if (!parameter)
  2437. return ScriptError(ERR_PARAM1_REQUIRED, aBuf);
  2438. // v1.0.32:
  2439. bool ignore_load_failure = (parameter[0] == '*' && toupper(parameter[1]) == 'I'); // Relies on short-circuit boolean order.
  2440. if (ignore_load_failure)
  2441. {
  2442. parameter += 2;
  2443. if (IS_SPACE_OR_TAB(*parameter)) // Skip over at most one space or tab, since others might be a literal part of the filename.
  2444. ++parameter;
  2445. }
  2446. size_t space_remaining = LINE_SIZE - (parameter-aBuf);
  2447. char buf[MAX_PATH];
  2448. StrReplace(parameter, "%A_ScriptDir%", mFileDir, SCS_INSENSITIVE, 1, space_remaining); // v1.0.35.11. Caller has ensured string is writable.
  2449. if (strcasestr(parameter, "%A_AppData%")) // v1.0.45.04: This and the next were requested by Tekl to make it easier to customize scripts on a per-user basis.
  2450. {
  2451. BIV_AppData(buf, "A_AppData");
  2452. StrReplace(parameter, "%A_AppData%", buf, SCS_INSENSITIVE, 1, space_remaining);
  2453. }
  2454. if (strcasestr(parameter, "%A_AppDataCommon%")) // v1.0.45.04.
  2455. {
  2456. BIV_AppData(buf, "A_AppDataCommon");
  2457. StrReplace(parameter, "%A_AppDataCommon%", buf, SCS_INSENSITIVE, 1, space_remaining);
  2458. }
  2459. DWORD attr = GetFileAttributes(parameter);
  2460. if (attr != 0xFFFFFFFF && (attr & FILE_ATTRIBUTE_DIRECTORY)) // File exists and its a directory (possibly A_ScriptDir or A_AppData set above).
  2461. {
  2462. // v1.0.35.11 allow changing of load-time directory to increase flexibility. This feature has
  2463. // been asked for directly or indirectly several times.
  2464. // If a script ever wants to use a string like "%A_ScriptDir%" literally in an include's filename,
  2465. // that would not work. But that seems too rare to worry about.
  2466. // v1.0.45.01: Call SetWorkingDir() vs. SetCurrentDirectory() so that it succeeds even for a root
  2467. // drive like C: that lacks a backslash (see SetWorkingDir() for details).
  2468. SetWorkingDir(parameter);
  2469. return CONDITION_TRUE;
  2470. }
  2471. // Since above didn't return, it's a file (or non-existent file, in which case the below will display
  2472. // the error). This will also display any other errors that occur:
  2473. return LoadIncludedFile(parameter, is_include_again, ignore_load_failure) ? CONDITION_TRUE : FAIL;
  2474. #endif
  2475. }
  2476. if (IS_DIRECTIVE_MATCH("#NoEnv"))
  2477. {
  2478. g_NoEnv = TRUE;
  2479. return CONDITION_TRUE;
  2480. }
  2481. if (IS_DIRECTIVE_MATCH("#NoTrayIcon"))
  2482. {
  2483. g_NoTrayIcon = true;
  2484. return CONDITION_TRUE;
  2485. }
  2486. if (IS_DIRECTIVE_MATCH("#Persistent"))
  2487. {
  2488. g_persistent = true;
  2489. return CONDITION_TRUE;
  2490. }
  2491. if (IS_DIRECTIVE_MATCH("#SingleInstance"))
  2492. {
  2493. g_AllowOnlyOneInstance = SINGLE_INSTANCE_PROMPT; // Set default.
  2494. if (parameter)
  2495. {
  2496. if (!stricmp(parameter, "Force"))
  2497. g_AllowOnlyOneInstance = SINGLE_INSTANCE_REPLACE;
  2498. else if (!stricmp(parameter, "Ignore"))
  2499. g_AllowOnlyOneInstance = SINGLE_INSTANCE_IGNORE;
  2500. else if (!stricmp(parameter, "Off"))
  2501. g_AllowOnlyOneInstance = SINGLE_INSTANCE_OFF;
  2502. }
  2503. return CONDITION_TRUE;
  2504. }
  2505. if (IS_DIRECTIVE_MATCH("#InstallKeybdHook"))
  2506. {
  2507. // It seems best not to report this warning because a user may want to use partial functionality
  2508. // of a script on Win9x:
  2509. //MsgBox("#InstallKeybdHook is not supported on Windows 95/98/Me. This line will be ignored.");
  2510. if (!g_os.IsWin9x())
  2511. Hotkey::RequireHook(HOOK_KEYBD);
  2512. return CONDITION_TRUE;
  2513. }
  2514. if (IS_DIRECTIVE_MATCH("#InstallMouseHook"))
  2515. {
  2516. // It seems best not to report this warning because a user may want to use partial functionality
  2517. // of a script on Win9x:
  2518. //MsgBox("#InstallMouseHook is not supported on Windows 95/98/Me. This line will be ignored.");
  2519. if (!g_os.IsWin9x())
  2520. Hotkey::RequireHook(HOOK_MOUSE);
  2521. return CONDITION_TRUE;
  2522. }
  2523. if (IS_DIRECTIVE_MATCH("#UseHook"))
  2524. {
  2525. g_ForceKeybdHook = !parameter || Line::ConvertOnOff(parameter) != TOGGLED_OFF;
  2526. return CONDITION_TRUE;
  2527. }
  2528. if (!strnicmp(aBuf, "#IfWin", 6))
  2529. {
  2530. bool invert = !strnicmp(aBuf + 6, "Not", 3);
  2531. if (!strnicmp(aBuf + (invert ? 9 : 6), "Active", 6)) // It matches #IfWin[Not]Active.
  2532. g_HotCriterion = invert ? HOT_IF_NOT_ACTIVE : HOT_IF_ACTIVE;
  2533. else if (!strnicmp(aBuf + (invert ? 9 : 6), "Exist", 5))
  2534. g_HotCriterion = invert ? HOT_IF_NOT_EXIST : HOT_IF_EXIST;
  2535. else // It starts with #IfWin but isn't Active or Exist: Don't alter g_HotCriterion.
  2536. return CONDITION_FALSE; // Indicate unknown directive since there are currently no other possibilities.
  2537. if (!parameter) // The omission of the parameter indicates that any existing criteria should be turned off.
  2538. {
  2539. g_HotCriterion = HOT_NO_CRITERION; // Indicate that no criteria are in effect for subsequent hotkeys.
  2540. g_HotWinTitle = ""; // Helps maintainability and some things might rely on it.
  2541. g_HotWinText = ""; //
  2542. return CONDITION_TRUE;
  2543. }
  2544. char *hot_win_title = parameter, *hot_win_text; // Set default for title; text is determined later.
  2545. // Scan for the first non-escaped comma. If there is one, it marks the second paramter: WinText.
  2546. char *cp, *first_non_escaped_comma;
  2547. for (first_non_escaped_comma = NULL, cp = hot_win_title; ; ++cp) // Increment to skip over the symbol just found by the inner for().
  2548. {
  2549. for (; *cp && !(*cp == g_EscapeChar || *cp == g_delimiter || *cp == g_DerefChar); ++cp); // Find the next escape char, comma, or %.
  2550. if (!*cp) // End of string was found.
  2551. break;
  2552. #define ERR_ESCAPED_COMMA_PERCENT "Literal commas and percent signs must be escaped (e.g. `%)"
  2553. if (*cp == g_DerefChar)
  2554. return ScriptError(ERR_ESCAPED_COMMA_PERCENT, aBuf);
  2555. if (*cp == g_delimiter) // non-escaped delimiter was found.
  2556. {
  2557. // Preserve the ability to add future-use parameters such as section of window
  2558. // over which the mouse is hovering, e.g. #IfWinActive, Untitled - Notepad,, TitleBar
  2559. if (first_non_escaped_comma) // A second non-escaped comma was found.
  2560. return ScriptError(ERR_ESCAPED_COMMA_PERCENT, aBuf);
  2561. // Otherwise:
  2562. first_non_escaped_comma = cp;
  2563. continue; // Check if there are any more non-escaped commas.
  2564. }
  2565. // Otherwise, an escape character was found, so skip over the next character (if any).
  2566. if (!*(++cp)) // The string unexpectedly ends in an escape character, so avoid out-of-bounds.
  2567. break;
  2568. // Otherwise, the ++cp above has skipped over the escape-char itself, and the loop's ++cp will now
  2569. // skip over the char-to-be-escaped, which is not the one we want (even if it is a comma).
  2570. }
  2571. if (first_non_escaped_comma) // Above found a non-escaped comma, so there is a second parameter (WinText).
  2572. {
  2573. // Omit whitespace to (seems best to conform to convention/expectations rather than give
  2574. // strange whitespace flexibility that would likely cause unwanted bugs due to inadvertently
  2575. // have two spaces instead of one). The user may use `s and `t to put literal leading/trailing
  2576. // spaces/tabs into these paramters.
  2577. hot_win_text = omit_leading_whitespace(first_non_escaped_comma + 1);
  2578. *first_non_escaped_comma = '\0'; // Terminate at the comma to split off hot_win_title on its own.
  2579. rtrim(hot_win_title, first_non_escaped_comma - hot_win_title); // Omit whitespace (see similar comment above).
  2580. // The following must be done only after trimming and omitting whitespace above, so that
  2581. // `s and `t can be used to insert leading/trailing spaces/tabs. ConvertEscapeSequences()
  2582. // also supports insertion of literal commas via escaped sequences.
  2583. ConvertEscapeSequences(hot_win_text, g_EscapeChar, true);
  2584. }
  2585. else
  2586. hot_win_text = ""; // And leave hot_win_title set to the entire string because there's only one parameter.
  2587. // The following must be done only after trimming and omitting whitespace above (see similar comment above).
  2588. ConvertEscapeSequences(hot_win_title, g_EscapeChar, true);
  2589. // The following also handles the case where both title and text are blank, which could happen
  2590. // due to something weird but legit like: #IfWinActive, ,
  2591. if (!SetGlobalHotTitleText(hot_win_title, hot_win_text))
  2592. return ScriptError(ERR_OUTOFMEM); // So rare that no second param is provided (since its contents may have been temp-terminated or altered above).
  2593. return CONDITION_TRUE;
  2594. } // Above completely handles all directives and non-directives that start with "#IfWin".
  2595. if (IS_DIRECTIVE_MATCH("#Hotstring"))
  2596. {
  2597. if (parameter)
  2598. {
  2599. char *suboption = strcasestr(parameter, "EndChars");
  2600. if (suboption)
  2601. {
  2602. // Since it's not realistic to have only a couple, spaces and literal tabs
  2603. // must be included in between other chars, e.g. `n `t has a space in between.
  2604. // Also, EndChar \t will have a space and a tab since there are two spaces
  2605. // after the word EndChar.
  2606. if ( !(parameter = StrChrAny(suboption, "\t ")) )
  2607. return CONDITION_TRUE;
  2608. strlcpy(g_EndChars, ++parameter, sizeof(g_EndChars));
  2609. ConvertEscapeSequences(g_EndChars, g_EscapeChar, false);
  2610. return CONDITION_TRUE;
  2611. }
  2612. if (!strnicmp(parameter, "NoMouse", 7)) // v1.0.42.03
  2613. {
  2614. g_HSResetUponMouseClick = false;
  2615. return CONDITION_TRUE;
  2616. }
  2617. // Otherwise assume it's a list of options. Note that for compatibility with its
  2618. // other caller, it will stop at end-of-string or ':', whichever comes first.
  2619. Hotstring::ParseOptions(parameter, g_HSPriority, g_HSKeyDelay, g_HSSendMode, g_HSCaseSensitive
  2620. , g_HSConformToCase, g_HSDoBackspace, g_HSOmitEndChar, g_HSSendRaw, g_HSEndCharRequired
  2621. , g_HSDetectWhenInsideWord, g_HSDoReset);
  2622. }
  2623. return CONDITION_TRUE;
  2624. }
  2625. if (IS_DIRECTIVE_MATCH("#HotkeyModifierTimeout"))
  2626. {
  2627. if (parameter)
  2628. g_HotkeyModifierTimeout = ATOI(parameter); // parameter was set to the right position by the above macro
  2629. return CONDITION_TRUE;
  2630. }
  2631. if (IS_DIRECTIVE_MATCH("#HotkeyInterval"))
  2632. {
  2633. if (parameter)
  2634. {
  2635. g_HotkeyThrottleInterval = ATOI(parameter); // parameter was set to the right position by the above macro
  2636. if (g_HotkeyThrottleInterval < 10) // values under 10 wouldn't be useful due to timer granularity.
  2637. g_HotkeyThrottleInterval = 10;
  2638. }
  2639. return CONDITION_TRUE;
  2640. }
  2641. if (IS_DIRECTIVE_MATCH("#MaxHotkeysPerInterval"))
  2642. {
  2643. if (parameter)
  2644. {
  2645. g_MaxHotkeysPerInterval = ATOI(parameter); // parameter was set to the right position by the above macro
  2646. if (g_MaxHotkeysPerInterval < 1) // sanity check
  2647. g_MaxHotkeysPerInterval = 1;
  2648. }
  2649. return CONDITION_TRUE;
  2650. }
  2651. if (IS_DIRECTIVE_MATCH("#MaxThreadsPerHotkey"))
  2652. {
  2653. if (parameter)
  2654. {
  2655. // Use value as a temp holder since it's int vs. UCHAR and can thus detect very large or negative values:
  2656. value = ATOI(parameter); // parameter was set to the right position by the above macro
  2657. if (value > MAX_THREADS_LIMIT) // For now, keep this limited to prevent stack overflow due to too many pseudo-threads.
  2658. value = MAX_THREADS_LIMIT; // UPDATE: To avoid array overflow, this limit must by obeyed except where otherwise documented.
  2659. else if (value < 1)
  2660. value = 1;
  2661. g_MaxThreadsPerHotkey = value; // Note: g_MaxThreadsPerHotkey is UCHAR.
  2662. }
  2663. return CONDITION_TRUE;
  2664. }
  2665. if (IS_DIRECTIVE_MATCH("#MaxThreadsBuffer"))
  2666. {
  2667. g_MaxThreadsBuffer = !parameter || Line::ConvertOnOff(parameter) != TOGGLED_OFF;
  2668. return CONDITION_TRUE;
  2669. }
  2670. if (IS_DIRECTIVE_MATCH("#MaxThreads"))
  2671. {
  2672. if (parameter)
  2673. {
  2674. value = ATOI(parameter); // parameter was set to the right position by the above macro
  2675. if (value > MAX_THREADS_LIMIT) // For now, keep this limited to prevent stack overflow due to too many pseudo-threads.
  2676. value = MAX_THREADS_LIMIT; // UPDATE: To avoid array overflow, this limit must by obeyed except where otherwise documented.
  2677. else if (value < 1)
  2678. value = 1;
  2679. g_MaxThreadsTotal = value;
  2680. }
  2681. return CONDITION_TRUE;
  2682. }
  2683. if (IS_DIRECTIVE_MATCH("#ClipboardTimeout"))
  2684. {
  2685. if (parameter)
  2686. g_ClipboardTimeout = ATOI(parameter); // parameter was set to the right position by the above macro
  2687. return CONDITION_TRUE;
  2688. }
  2689. if (IS_DIRECTIVE_MATCH("#LTrim"))
  2690. {
  2691. g_ContinuationLTrim = !parameter || Line::ConvertOnOff(parameter) != TOGGLED_OFF;
  2692. return CONDITION_TRUE;
  2693. }
  2694. if (IS_DIRECTIVE_MATCH("#WinActivateForce"))
  2695. {
  2696. g_WinActivateForce = true;
  2697. return CONDITION_TRUE;
  2698. }
  2699. if (IS_DIRECTIVE_MATCH("#ErrorStdOut"))
  2700. {
  2701. mErrorStdOut = true;
  2702. return CONDITION_TRUE;
  2703. }
  2704. if (IS_DIRECTIVE_MATCH("#AllowSameLineComments")) // i.e. There's no way to turn it off, only on.
  2705. {
  2706. g_AllowSameLineComments = true;
  2707. return CONDITION_TRUE;
  2708. }
  2709. if (IS_DIRECTIVE_MATCH("#MaxMem"))
  2710. {
  2711. if (parameter)
  2712. {
  2713. double valuef = ATOF(parameter); // parameter was set to the right position by the above macro
  2714. if (valuef > 4095) // Don't exceed capacity of VarSizeType, which is currently a DWORD (4 gig).
  2715. valuef = 4095; // Don't use 4096 since that might be a special/reserved value for some functions.
  2716. else if (valuef < 1)
  2717. valuef = 1;
  2718. g_MaxVarCapacity = (VarSizeType)(valuef * 1024 * 1024);
  2719. }
  2720. return CONDITION_TRUE;
  2721. }
  2722. if (IS_DIRECTIVE_MATCH("#KeyHistory"))
  2723. {
  2724. if (parameter)
  2725. {
  2726. g_MaxHistoryKeys = ATOI(parameter); // parameter was set to the right position by the above macro
  2727. if (g_MaxHistoryKeys < 0)
  2728. g_MaxHistoryKeys = 0;
  2729. else if (g_MaxHistoryKeys > 500)
  2730. g_MaxHistoryKeys = 500;
  2731. // Above: There are two reasons for limiting the history file to 500 keystrokes:
  2732. // 1) GetHookStatus() only has a limited size buffer in which to transcribe the keystrokes.
  2733. // 500 events is about what you would expect to fit in a 32 KB buffer (it the unlikely event
  2734. // that the transcribed events create too much text, the text will be truncated, so it's
  2735. // not dangerous anyway).
  2736. // 2) To reduce the impression that AutoHotkey designed for key logging (the key history file
  2737. // is in a very unfriendly format that type of key logging anyway).
  2738. }
  2739. return CONDITION_TRUE;
  2740. }
  2741. // For the below series, it seems okay to allow the comment flag to contain other reserved chars,
  2742. // such as DerefChar, since comments are evaluated, and then taken out of the game at an earlier
  2743. // stage than DerefChar and the other special chars.
  2744. if (IS_DIRECTIVE_MATCH("#CommentFlag"))
  2745. {
  2746. if (parameter)
  2747. {
  2748. if (!*(parameter + 1)) // i.e. the length is 1
  2749. {
  2750. // Don't allow '#' since it's the preprocessor directive symbol being used here.
  2751. // Seems ok to allow "." to be the comment flag, since other constraints mandate
  2752. // that at least one space or tab occur to its left for it to be considered a
  2753. // comment marker.
  2754. if (*parameter == '#' || *parameter == g_DerefChar || *parameter == g_EscapeChar || *parameter == g_delimiter)
  2755. return ScriptError(ERR_PARAM1_INVALID, aBuf);
  2756. // Exclude hotkey definition chars, such as ^ and !, because otherwise
  2757. // the following example wouldn't work:
  2758. // User defines ! as the comment flag.
  2759. // The following hotkey would never be in effect since it's considered to
  2760. // be commented out:
  2761. // !^a::run,notepad
  2762. if (*parameter == '!' || *parameter == '^' || *parameter == '+' || *parameter == '$' || *parameter == '~' || *parameter == '*'
  2763. || *parameter == '<' || *parameter == '>')
  2764. // Note that '#' is already covered by the other stmt. above.
  2765. return ScriptError(ERR_PARAM1_INVALID, aBuf);
  2766. }
  2767. strlcpy(g_CommentFlag, parameter, MAX_COMMENT_FLAG_LENGTH + 1);
  2768. g_CommentFlagLength = strlen(g_CommentFlag); // Keep this in sync with above.
  2769. }
  2770. return CONDITION_TRUE;
  2771. }
  2772. if (IS_DIRECTIVE_MATCH("#EscapeChar"))
  2773. {
  2774. if (parameter)
  2775. {
  2776. // Don't allow '.' since that can be part of literal floating point numbers:
  2777. if ( *parameter == '#' || *parameter == g_DerefChar || *parameter == g_delimiter || *parameter == '.'
  2778. || (g_CommentFlagLength == 1 && *parameter == *g_CommentFlag) )
  2779. return ScriptError(ERR_PARAM1_INVALID, aBuf);
  2780. g_EscapeChar = *parameter;
  2781. }
  2782. return CONDITION_TRUE;
  2783. }
  2784. if (IS_DIRECTIVE_MATCH("#DerefChar"))
  2785. {
  2786. if (parameter)
  2787. {
  2788. if ( *parameter == g_EscapeChar || *parameter == g_delimiter || *parameter == '.'
  2789. || (g_CommentFlagLength == 1 && *parameter == *g_CommentFlag) ) // Fix for v1.0.47.05: Allow deref char to be # as documented.
  2790. return ScriptError(ERR_PARAM1_INVALID, aBuf);
  2791. g_DerefChar = *parameter;
  2792. }
  2793. return CONDITION_TRUE;
  2794. }
  2795. if (IS_DIRECTIVE_MATCH("#Delimiter"))
  2796. {
  2797. // Attempts to change the delimiter to its starting default (comma) are ignored.
  2798. // For example, "#Delimiter ," isn't meaningful if the delimiter already is a comma,
  2799. // which is good because "parameter" has already assumed that the comma is accidental
  2800. // (not a symbol) and omitted it.
  2801. if (parameter)
  2802. {
  2803. if ( *parameter == '#' || *parameter == g_EscapeChar || *parameter == g_DerefChar || *parameter == '.'
  2804. || (g_CommentFlagLength == 1 && *parameter == *g_CommentFlag) )
  2805. return ScriptError(ERR_PARAM1_INVALID, aBuf);
  2806. g_delimiter = *parameter;
  2807. }
  2808. return CONDITION_TRUE;
  2809. }
  2810. // Otherwise, report that this line isn't a directive:
  2811. return CONDITION_FALSE;
  2812. }
  2813. void ScriptTimer::Disable()
  2814. {
  2815. mEnabled = false;
  2816. --g_script.mTimerEnabledCount;
  2817. if (!g_script.mTimerEnabledCount && !g_nLayersNeedingTimer && !Hotkey::sJoyHotkeyCount)
  2818. KILL_MAIN_TIMER
  2819. // Above: If there are now no enabled timed subroutines, kill the main timer since there's no other
  2820. // reason for it to exist if we're here. This is because or direct or indirect caller is
  2821. // currently always ExecUntil(), which doesn't need the timer while its running except to
  2822. // support timed subroutines. UPDATE: The above is faulty; Must also check g_nLayersNeedingTimer
  2823. // because our caller can be one that still needs a timer as proven by this script that
  2824. // hangs otherwise:
  2825. //SetTimer, Test, on
  2826. //Sleep, 1000
  2827. //msgbox, done
  2828. //return
  2829. //Test:
  2830. //SetTimer, Test, off
  2831. //return
  2832. }
  2833. ResultType Script::UpdateOrCreateTimer(Label *aLabel, char *aPeriod, char *aPriority, bool aEnable
  2834. , bool aUpdatePriorityOnly)
  2835. // Caller should specific a blank aPeriod to prevent the timer's period from being changed
  2836. // (i.e. if caller just wants to turn on or off an existing timer). But if it does this
  2837. // for a non-existent timer, that timer will be created with the default period as specfied in
  2838. // the constructor.
  2839. {
  2840. ScriptTimer *timer;
  2841. for (timer = mFirstTimer; timer != NULL; timer = timer->mNextTimer)
  2842. if (timer->mLabel == aLabel) // Match found.
  2843. break;
  2844. bool timer_existed = (timer != NULL);
  2845. if (!timer_existed) // Create it.
  2846. {
  2847. if ( !(timer = new ScriptTimer(aLabel)) )
  2848. return ScriptError(ERR_OUTOFMEM);
  2849. if (!mFirstTimer)
  2850. mFirstTimer = mLastTimer = timer;
  2851. else
  2852. {
  2853. mLastTimer->mNextTimer = timer;
  2854. // This must be done after the above:
  2855. mLastTimer = timer;
  2856. }
  2857. ++mTimerCount;
  2858. }
  2859. // Update its members:
  2860. if (aEnable && !timer->mEnabled) // Must check both or the mTimerEnabledCount below will be wrong.
  2861. {
  2862. // The exception is if the timer already existed but the caller only wanted its priority changed:
  2863. if (!(timer_existed && aUpdatePriorityOnly))
  2864. {
  2865. timer->mEnabled = true;
  2866. ++mTimerEnabledCount;
  2867. SET_MAIN_TIMER // Ensure the API timer is always running when there is at least one enabled timed subroutine.
  2868. }
  2869. //else do nothing, leave it disabled.
  2870. }
  2871. else if (!aEnable && timer->mEnabled) // Must check both or the below count will be wrong.
  2872. timer->Disable();
  2873. if (*aPeriod) // Caller wanted us to update this member.
  2874. {
  2875. __int64 period = ATOI64(aPeriod);
  2876. if (period < 0) // v1.0.46.16: Support negative periods to mean "run only once".
  2877. {
  2878. timer->mRunOnlyOnce = true;
  2879. timer->mPeriod = (DWORD)-period;
  2880. }
  2881. else // Positive number. v1.0.36.33: Changed from int to DWORD, and ATOI to ATOU, to double its capacity:
  2882. {
  2883. timer->mPeriod = (DWORD)period; // Always use this method & check to retain compatibility with existing scripts.
  2884. timer->mRunOnlyOnce = false;
  2885. }
  2886. }
  2887. if (*aPriority) // Caller wants this member to be changed from its current or default value.
  2888. timer->mPriority = ATOI(aPriority); // Read any float in a runtime variable reference as an int.
  2889. if (!(timer_existed && aUpdatePriorityOnly))
  2890. // Caller relies on us updating mTimeLastRun in this case. This is done because it's more
  2891. // flexible, e.g. a user might want to create a timer that is triggered 5 seconds from now.
  2892. // In such a case, we don't want the timer's first triggering to occur immediately.
  2893. // Instead, we want it to occur only when the full 5 seconds have elapsed:
  2894. timer->mTimeLastRun = GetTickCount();
  2895. // Below is obsolete, see above for why:
  2896. // We don't have to kill or set the main timer because the only way this function is called
  2897. // is directly from the execution of a script line inside ExecUntil(), in which case:
  2898. // 1) KILL_MAIN_TIMER is never needed because the timer shouldn't exist while in ExecUntil().
  2899. // 2) SET_MAIN_TIMER is never needed because it will be set automatically the next time ExecUntil()
  2900. // calls MsgSleep().
  2901. return OK;
  2902. }
  2903. Label *Script::FindLabel(char *aLabelName)
  2904. // Returns the first label whose name matches aLabelName, or NULL if not found.
  2905. // v1.0.42: Since duplicates labels are now possible (to support #IfWin variants of a particular
  2906. // hotkey or hotstring), callers must be aware that only the first match is returned.
  2907. // This helps performance by requiring on average only half the labels to be searched before
  2908. // a match is found.
  2909. {
  2910. if (!aLabelName || !*aLabelName) return NULL;
  2911. for (Label *label = mFirstLabel; label != NULL; label = label->mNextLabel)
  2912. if (!stricmp(label->mName, aLabelName)) // lstrcmpi() is not used: 1) avoids breaking exisitng scripts; 2) provides consistent behavior across multiple locales; 3) performance.
  2913. return label; // Match found.
  2914. return NULL; // No match found.
  2915. }
  2916. ResultType Script::AddLabel(char *aLabelName, bool aAllowDupe)
  2917. // Returns OK or FAIL.
  2918. {
  2919. if (!*aLabelName)
  2920. return FAIL; // For now, silent failure because callers should check this beforehand.
  2921. if (!aAllowDupe && FindLabel(aLabelName)) // Relies on short-circuit boolean order.
  2922. // Don't attempt to dereference "duplicate_label->mJumpToLine because it might not
  2923. // exist yet. Example:
  2924. // label1:
  2925. // label1: <-- This would be a dupe-error but it doesn't yet have an mJumpToLine.
  2926. // return
  2927. return ScriptError("Duplicate label.", aLabelName);
  2928. char *new_name = SimpleHeap::Malloc(aLabelName);
  2929. if (!new_name)
  2930. return FAIL; // It already displayed the error for us.
  2931. Label *the_new_label = new Label(new_name); // Pass it the dynamic memory area we created.
  2932. if (the_new_label == NULL)
  2933. return ScriptError(ERR_OUTOFMEM);
  2934. the_new_label->mPrevLabel = mLastLabel; // Whether NULL or not.
  2935. if (mFirstLabel == NULL)
  2936. mFirstLabel = the_new_label;
  2937. else
  2938. mLastLabel->mNextLabel = the_new_label;
  2939. // This must be done after the above:
  2940. mLastLabel = the_new_label;
  2941. if (!stricmp(new_name, "OnClipboardChange"))
  2942. mOnClipboardChangeLabel = the_new_label;
  2943. return OK;
  2944. }
  2945. ResultType Script::ParseAndAddLine(char *aLineText, ActionTypeType aActionType, ActionTypeType aOldActionType
  2946. , char *aActionName, char *aEndMarker, char *aLiteralMap, size_t aLiteralMapLength)
  2947. // Returns OK or FAIL.
  2948. // aLineText needs to be a string whose contents are modifiable (though the string won't be made any
  2949. // longer than it is now, so it doesn't have to be of size LINE_SIZE). This helps performance by
  2950. // allowing the string to be split into sections without having to make temporary copies.
  2951. {
  2952. #ifdef _DEBUG
  2953. if (!aLineText || !*aLineText)
  2954. return ScriptError("DEBUG: ParseAndAddLine() called incorrectly.");
  2955. #endif
  2956. bool in_quotes;
  2957. int open_parens;
  2958. char action_name[MAX_VAR_NAME_LENGTH + 1], *end_marker;
  2959. if (aActionName) // i.e. this function was called recursively with explicit values for the optional params.
  2960. {
  2961. strcpy(action_name, aActionName);
  2962. end_marker = aEndMarker;
  2963. }
  2964. else if (aActionType == ACT_EXPRESSION)
  2965. {
  2966. *action_name = '\0';
  2967. end_marker = NULL; // Indicate that there is no action to mark the end of.
  2968. }
  2969. else // We weren't called recursively from self, nor is it ACT_EXPRESSION, so set action_name and end_marker the normal way.
  2970. {
  2971. for (;;) // A loop with only one iteration so that "break" can be used instead of a lot of nested if's.
  2972. {
  2973. if (!g->CurrentFunc) // Not inside a function body, so "Global"/"Local"/"Static" get no special treatment.
  2974. break;
  2975. int declare_type;
  2976. char *cp;
  2977. if (!strnicmp(aLineText, "Global", 6)) // Checked first because it's more common than the others.
  2978. {
  2979. cp = aLineText + 6; // The character after the declaration word.
  2980. declare_type = VAR_DECLARE_GLOBAL;
  2981. }
  2982. else if (!strnicmp(aLineText, "Local", 5))
  2983. {
  2984. cp = aLineText + 5; // The character after the declaration word.
  2985. declare_type = VAR_DECLARE_LOCAL;
  2986. }
  2987. else if (!strnicmp(aLineText, "Static", 6)) // Static also implies local (for functions that default to global).
  2988. {
  2989. cp = aLineText + 6; // The character after the declaration word.
  2990. declare_type = VAR_DECLARE_STATIC;
  2991. }
  2992. else // It's not the word "global", "local", or static, so no further checking is done.
  2993. break;
  2994. if (*cp && !IS_SPACE_OR_TAB(*cp)) // There is a character following the word local but it's not a space or tab.
  2995. break; // It doesn't qualify as being the global or local keyword because it's something like global2.
  2996. if (*cp && *(cp = omit_leading_whitespace(cp))) // Probably always a true stmt since caller rtrimmed it, but even if not it's handled correctly.
  2997. {
  2998. // Check whether the first character is an operator by seeing if it alone would be a
  2999. // valid variable name. If it's not valid, this doesn't qualify as the global or local
  3000. // keyword because it's something like this instead:
  3001. // local := xyz
  3002. // local += 3
  3003. char orig_char = cp[1];
  3004. cp[1] = '\0'; // Temporarily terminate.
  3005. ResultType result = Var::ValidateName(cp, false, DISPLAY_NO_ERROR);
  3006. cp[1] = orig_char; // Undo the termination.
  3007. if (!result) // It's probably operator, e.g. local = %var%
  3008. break;
  3009. }
  3010. else // It's the word "global", "local", "static" by itself. But only global or static is valid that way (when it's the first line in the function body).
  3011. {
  3012. // All of the following must be checked to catch back-to-back conflicting declarations such
  3013. // as these:
  3014. // global x
  3015. // global ; Should be an error because global vars are implied/automatic.
  3016. // v1.0.48: Lexikos: Added assume-static mode. For now, this requires "static" to be
  3017. // placed above local or global variable declarations.
  3018. if (declare_type != VAR_DECLARE_LOCAL // i.e. VAR_DECLARE_GLOBAL or VAR_DECLARE_STATIC (can't due be VAR_DECLARE_NONE due to checks higher above).
  3019. && mNextLineIsFunctionBody && g->CurrentFunc->mDefaultVarType == VAR_DECLARE_NONE)
  3020. {
  3021. g->CurrentFunc->mDefaultVarType = declare_type;
  3022. // No further action is required for the word "global" or "static" by itself.
  3023. return OK;
  3024. }
  3025. // Otherwise, it's the word "local" by itself (which isn't allowed since it's the default),
  3026. // or it's the word global or static by itself, but it occurs too far down in the body.
  3027. return ScriptError(ERR_UNRECOGNIZED_ACTION, aLineText); // Vague error since so rare.
  3028. }
  3029. if (mNextLineIsFunctionBody && g->CurrentFunc->mDefaultVarType == VAR_DECLARE_NONE)
  3030. {
  3031. // Both of the above must be checked to catch back-to-back conflicting declarations such
  3032. // as these:
  3033. // local x
  3034. // global y ; Should be an error because global vars are implied/automatic.
  3035. // This line will become first non-directive, non-label line in the function's body.
  3036. // If the first non-directive, non-label line in the function's body contains
  3037. // the "local" keyword, everything inside this function will assume that variables
  3038. // are global unless they are explicitly declared local (this is the opposite of
  3039. // the default). The converse is also true. UPDATE: "static" must also force ASSUME_LOCAL
  3040. // into effect because otherwise statics wouldn't go into the exception list and thus
  3041. // wouldn't be properly looked up when they're referenced throughout the function body.
  3042. // Therefore, if the first line of the function body is "static MyVar", VAR_DECLARE_LOCAL
  3043. // goes into effect permanently, which can be worked around by using the word "global"
  3044. // as the first word of the function instead.
  3045. g->CurrentFunc->mDefaultVarType = declare_type == VAR_DECLARE_LOCAL ? VAR_DECLARE_GLOBAL : VAR_DECLARE_LOCAL;
  3046. }
  3047. else // Since this isn't the first line of the function's body, mDefaultVarType has aleady been set permanently.
  3048. {
  3049. if (declare_type == g->CurrentFunc->mDefaultVarType) // Can't be VAR_DECLARE_NONE at this point.
  3050. {
  3051. // Seems best to flag redundant/unnecessary declarations since they might be an indication
  3052. // to the user that something is being done incorrectly in this function. This errors also
  3053. // remind the user what mode the function is in:
  3054. if (declare_type == VAR_DECLARE_GLOBAL)
  3055. return ScriptError("Global variables must not be declared in this function.", aLineText);
  3056. if (declare_type == VAR_DECLARE_LOCAL)
  3057. return ScriptError("Local variables must not be declared in this function.", aLineText);
  3058. // In assume-static mode, allow declarations in case they contain initializers.
  3059. // Would otherwise lose the ability to "initialize only once upon startup".
  3060. //if (declare_type == VAR_DECLARE_STATIC)
  3061. // return ScriptError("Static variables must not be declared in this function.", aLineText);
  3062. }
  3063. }
  3064. // Since above didn't break or return, a variable is being declared as an exception to the
  3065. // mode specified by mDefaultVarType.
  3066. // v1.0.48: A declaration is an exception to this function's assume-mode when the
  3067. // declaration's general nature as a local-or-global (in which static is considered local)
  3068. // differs from that of the current mode. In other words, a static or local declaration is
  3069. // not an exception unless this function is assume-global. Also, earlier logic has ensured
  3070. // that mDefaultVarType!=VAR_DECLARE_NONE by the time the first variable declaration is reached.
  3071. // Lexikos: Changed the following to support assume-static mode - i.e. when declaring a local,
  3072. // it is only an "exception" if the function is assume-global.
  3073. bool is_exception = ((declare_type == VAR_DECLARE_GLOBAL) != (g->CurrentFunc->mDefaultVarType == VAR_DECLARE_GLOBAL));
  3074. bool open_brace_was_added, belongs_to_if_or_else_or_loop;
  3075. VarSizeType var_name_length;
  3076. char *item;
  3077. for (belongs_to_if_or_else_or_loop = ACT_IS_IF_OR_ELSE_OR_LOOP(mLastLine->mActionType)
  3078. , open_brace_was_added = false, item = cp
  3079. ; *item;) // FOR EACH COMMA-SEPARATED ITEM IN THE DECLARATION LIST.
  3080. {
  3081. char *item_end = StrChrAny(item, ", \t=:"); // Comma, space or tab, equal-sign, colon.
  3082. if (!item_end) // This is probably the last/only variable in the list; e.g. the "x" in "local x"
  3083. item_end = item + strlen(item);
  3084. var_name_length = (VarSizeType)(item_end - item);
  3085. int always_use;
  3086. if (is_exception)
  3087. always_use = g->CurrentFunc->mDefaultVarType == VAR_DECLARE_GLOBAL ? ALWAYS_USE_LOCAL : ALWAYS_USE_GLOBAL;
  3088. else
  3089. always_use = ALWAYS_USE_DEFAULT;
  3090. Var *var;
  3091. bool is_already_exception;
  3092. if ( !(var = FindOrAddVar(item, var_name_length, always_use, &is_already_exception)) )
  3093. return FAIL; // It already displayed the error.
  3094. if (is_already_exception) // It was already in the exception list (previously declared).
  3095. return ScriptError("Duplicate declaration.", item);
  3096. if (var->Type() != VAR_NORMAL || !strlicmp(item, "ErrorLevel", var_name_length)) // Shouldn't be declared either way (global or local).
  3097. return ScriptError("Built-in variables must not be declared.", item);
  3098. for (int i = 0; i < g->CurrentFunc->mParamCount; ++i) // Search by name to find both global and local declarations.
  3099. if (!strlicmp(item, g->CurrentFunc->mParam[i].var->mName, var_name_length))
  3100. return ScriptError("Parameters must not be declared.", item);
  3101. if (is_exception)
  3102. {
  3103. if (mFuncExceptionVarCount >= MAX_FUNC_VAR_EXCEPTIONS)
  3104. return ScriptError("Too many declarations.", item); // Short message since it's so unlikely.
  3105. mFuncExceptionVar[mFuncExceptionVarCount++] = var;
  3106. }
  3107. if (declare_type == VAR_DECLARE_STATIC)
  3108. var->ConvertToStatic();
  3109. else if (declare_type == VAR_DECLARE_LOCAL && g->CurrentFunc->mDefaultVarType == VAR_DECLARE_STATIC) // v1.0.48: Lexikos.
  3110. // For explicitly-declared locals, remove VAR_ATTRIB_STATIC because AddVar() earlier set it
  3111. // as a default due to assume-static mode.
  3112. var->ConvertToNonStatic();
  3113. item_end = omit_leading_whitespace(item_end); // Move up to the next comma, assignment-op, or '\0'.
  3114. bool convert_the_operator;
  3115. switch(*item_end)
  3116. {
  3117. case ',': // No initializer is present for this variable, so move on to the next one.
  3118. item = omit_leading_whitespace(item_end + 1); // Set "item" for use by the next iteration.
  3119. continue; // No further processing needed below.
  3120. case '\0': // No initializer is present for this variable, so move on to the next one.
  3121. item = item_end; // Set "item" for use by the next iteration.
  3122. continue;
  3123. case ':':
  3124. if (item_end[1] != '=') // Colon with no following '='.
  3125. return ScriptError(ERR_UNRECOGNIZED_ACTION, item); // Vague error since so rare.
  3126. item_end += 2; // Point to the character after the ":=".
  3127. convert_the_operator = false;
  3128. break;
  3129. case '=': // Here '=' is clearly an assignment not a comparison, so further below it will be converted to :=
  3130. ++item_end; // Point to the character after the "=".
  3131. convert_the_operator = true;
  3132. break;
  3133. }
  3134. char *right_side_of_operator = item_end; // Save for use by VAR_DECLARE_STATIC below.
  3135. // Since above didn't "continue", this declared variable also has an initializer.
  3136. // Add that initializer as a separate line to be executed at runtime. Separate lines
  3137. // might actually perform better at runtime because most initializers tend to be simple
  3138. // literals or variables that are simplified into non-expressions at runtime. In addition,
  3139. // items without an initializer are omitted, further improving runtime performance.
  3140. // However, the following must be done ONLY after having done the FindOrAddVar()
  3141. // above, since that may have changed this variable to a non-default type (local or global).
  3142. // But what about something like "global x, y=x"? Even that should work as long as x
  3143. // appears in the list prior to initializers that use it.
  3144. // Now, find the comma (or terminator) that marks the end of this sub-statement.
  3145. // The search must exclude commas that are inside quoted/literal strings and those that
  3146. // are inside parentheses (chiefly those of function-calls, but possibly others).
  3147. for (in_quotes = false, open_parens = 0; *item_end; ++item_end) // FIND THE NEXT "REAL" COMMA.
  3148. {
  3149. if (*item_end == ',') // This is outside the switch() further below so that its "break" can get out of the loop.
  3150. {
  3151. if (!in_quotes && open_parens < 1) // A delimiting comma other than one in a sub-statement or function. Shouldn't need to worry about unquoted escaped commas since they don't make sense in a declaration list.
  3152. break;
  3153. // Otherwise, its a quoted/literal comma or one in parentheses (such as function-call).
  3154. continue; // Continue past it to look for the correct comma.
  3155. }
  3156. switch (*item_end)
  3157. {
  3158. case '"': // There are sections similar this one later below; so see them for comments.
  3159. in_quotes = !in_quotes;
  3160. break;
  3161. case '(':
  3162. if (!in_quotes) // Literal parentheses inside a quoted string should not be counted for this purpose.
  3163. ++open_parens;
  3164. break;
  3165. case ')':
  3166. if (!in_quotes)
  3167. {
  3168. if (!open_parens)
  3169. return ScriptError(ERR_MISSING_OPEN_PAREN, item);
  3170. --open_parens;
  3171. }
  3172. break;
  3173. //default: some other character; just have the loop skip over it.
  3174. }
  3175. } // for() to look for the ending comma or terminator of this sub-statement.
  3176. if (open_parens) // At least one '(' is never closed.
  3177. return ScriptError(ERR_MISSING_CLOSE_PAREN, item); // Use "item" because the problem is probably somewhere after that point in the declaration list.
  3178. if (in_quotes)
  3179. return ScriptError(ERR_MISSING_CLOSE_QUOTE, item);
  3180. // Above has now found the final comma of this sub-statement (or the terminator if there is no comma).
  3181. char *terminate_here = omit_trailing_whitespace(item, item_end-1) + 1; // v1.0.47.02: Fix the fact that "x=5 , y=6" would preserve the whitespace at the end of "5". It also fixes wrongly showing a syntax error for things like: static d="xyz" , e = 5
  3182. char orig_char = *terminate_here;
  3183. *terminate_here = '\0'; // Temporarily terminate (it might already be the terminator, but that's harmless).
  3184. if (declare_type == VAR_DECLARE_STATIC) // v1.0.46: Support simple initializers for static variables.
  3185. {
  3186. // The following is similar to the code used to support default values for function parameters.
  3187. // So maybe maintain them together.
  3188. right_side_of_operator = omit_leading_whitespace(right_side_of_operator);
  3189. if (!stricmp(right_side_of_operator, "false"))
  3190. var->Assign("0");
  3191. else if (!stricmp(right_side_of_operator, "true"))
  3192. var->Assign("1");
  3193. else // The only other supported initializers are "string", integers, and floats.
  3194. {
  3195. // Vars could be supported here via FindVar(), but only globals ABOVE this point in
  3196. // the script would be supported (since other globals don't exist yet; in fact, even
  3197. // those that do exist don't have any contents yet, so it would be pointless). So it
  3198. // seems best to wait until full/comprehesive support for expressions is
  3199. // studied/designed for both statics and parameter-default-values.
  3200. if (*right_side_of_operator == '"' && terminate_here[-1] == '"') // Quoted/literal string.
  3201. {
  3202. ++right_side_of_operator; // Omit the opening-quote from further consideration.
  3203. terminate_here[-1] = '\0'; // Remove the close-quote from further consideration.
  3204. ConvertEscapeSequences(right_side_of_operator, g_EscapeChar, false); // Raw escape sequences like `n haven't been converted yet, so do it now.
  3205. // Convert all pairs of quotes into single literal quotes:
  3206. StrReplace(right_side_of_operator, "\"\"", "\"", SCS_SENSITIVE);
  3207. }
  3208. else // It's not a quoted string (nor the empty string); or it has a missing ending quote (rare).
  3209. {
  3210. if (!IsPureNumeric(right_side_of_operator, true, false, true)) // It's not a number, and since we're here it's not a quoted/literal string either.
  3211. return ScriptError("Unsupported static initializer.", right_side_of_operator);
  3212. //else it's an int or float, so just assign the numeric string itself (there
  3213. // doesn't seem to be any need to convert it to float/int first, though that would
  3214. // make things more consistent such as storing .1 as 0.1).
  3215. }
  3216. if (*right_side_of_operator) // It can be "" in cases such as "" being specified literally in the script, in which case nothing needs to be done because all variables start off as "".
  3217. var->Assign(right_side_of_operator);
  3218. }
  3219. }
  3220. else // A non-static initializer, so a line of code must be produced that will be executed at runtime every time the function is called.
  3221. {
  3222. // PERFORMANCE: As of v1.0.48 (with cached binary numbers and pre-postfixed expressions),
  3223. // assignments of literal integers to variables are up to 10% slower when done as a combined
  3224. // (comma-separated) expression rather than each as a separate line. However, this slowness
  3225. // eventually disappears and may even reverse as more and more such expressions are combined
  3226. // into a single expression (e.g. the following is almost the same speed either way:
  3227. // x:=1,y:=22,z:=333,a:=4444,b:=55555). By contrast, assigning a literal string, another
  3228. // variable, or a complex expression is the opposite: they are always faster when done via
  3229. // commas, and they continue to get faster and faster as more expressions are merged into a
  3230. // single comma-separated expression. In light of this, a future version could combine ONLY
  3231. // those declarations that have initializers into a single comma-separately expression rather
  3232. // than making a separate expression for each. However, since it's not always faster to do
  3233. // so (e.g. x:=0,y:=1 is faster as separate statements), and since it is somewhat rare to
  3234. // have a long chain of initializers, and since these performance differences are documented,
  3235. // it might not be worth changing.
  3236. char *line_to_add;
  3237. char new_buf[LINE_SIZE]; // Declared outside the braces below so that it stays in scope long enough. Using so much stack space here and in caller seems unlikely to affect performance, so _alloca seems unlikely to help.
  3238. if (convert_the_operator) // Convert first '=' in item to be ":=".
  3239. {
  3240. // Prevent any chance of overflow by using new_buf (overflow might otherwise occur in cases
  3241. // such as this sub-statement being the very last one in the declaration list, and being
  3242. // at the limit of the buffer's capacity).
  3243. StrReplace(strcpy(new_buf, item), "=", ":=", SCS_SENSITIVE, 1); // Can't overflow because there's only one replacement and we know item's length can't be that close to the capacity limit.
  3244. line_to_add = new_buf;
  3245. }
  3246. else
  3247. line_to_add = item;
  3248. if (belongs_to_if_or_else_or_loop && !open_brace_was_added) // v1.0.46.01: Put braces to allow initializers to work even directly under an IF/ELSE/LOOP. Note that the braces aren't added or needed for static initializers.
  3249. {
  3250. if (!AddLine(ACT_BLOCK_BEGIN))
  3251. return FAIL;
  3252. open_brace_was_added = true;
  3253. }
  3254. // Call Parse() vs. AddLine() because it detects and optimizes simple assignments into
  3255. // non-exprssions for faster runtime execution.
  3256. if (!ParseAndAddLine(line_to_add)) // For simplicity and maintainability, call self rather than trying to set things up properly to stay in self.
  3257. return FAIL; // Above already displayed the error.
  3258. }
  3259. *terminate_here = orig_char; // Undo the temporary termination.
  3260. // Set "item" for use by the next iteration:
  3261. item = (*item_end == ',') // i.e. it's not the terminator and thus not the final item in the list.
  3262. ? omit_leading_whitespace(item_end + 1)
  3263. : item_end; // It's the terminator, so let the loop detect that to finish.
  3264. } // for() each item in the declaration list.
  3265. if (open_brace_was_added)
  3266. if (!AddLine(ACT_BLOCK_END))
  3267. return FAIL;
  3268. return OK;
  3269. } // single-iteration for-loop
  3270. // Since above didn't return, it's not a declaration such as "global MyVar".
  3271. if ( !(end_marker = ParseActionType(action_name, aLineText, true)) )
  3272. return FAIL; // It already displayed the error.
  3273. }
  3274. // Above has ensured that end_marker is the address of the last character of the action name,
  3275. // or NULL if there is no action name.
  3276. // Find the arguments (not to be confused with exec_params) of this action, if it has any:
  3277. char *action_args = end_marker ? omit_leading_whitespace(end_marker + 1) : aLineText;
  3278. // Now action_args is either the first delimiter or the first parameter (if the optional first
  3279. // delimiter was omitted).
  3280. bool add_openbrace_afterward = false; // v1.0.41: Set default for use in supporting brace in "if (expr) {" and "Loop {".
  3281. if (*action_args == g_delimiter)
  3282. {
  3283. // Since there's a comma, don't change aActionType because if it's ACT_INVALID, it should stay that way
  3284. // so that "something, += 4" is not a valid assignment or other operator, but should still be checked
  3285. // against the list of commands to see if it's something like "MsgBox, += 4" (in this case, a script may
  3286. // use the comma to avoid ambiguity).
  3287. // Find the start of the next token (or its ending delimiter if the token is blank such as ", ,"):
  3288. for (++action_args; IS_SPACE_OR_TAB(*action_args); ++action_args);
  3289. }
  3290. else if (!aActionType && !aOldActionType) // i.e. the caller hasn't yet determined this line's action type.
  3291. {
  3292. if (!stricmp(action_name, "IF")) // It's an IF-statement.
  3293. {
  3294. /////////////////////////////////////
  3295. // Detect all types of IF-statements.
  3296. /////////////////////////////////////
  3297. char *operation, *next_word;
  3298. if ( *action_args == '(' // i.e. if (expression)
  3299. || *action_args == g_DerefChar && IS_SPACE_OR_TAB(action_args[1]) ) // v1.0.48.04: "if % expr" is always an expressions. This check was added to allow lines like "if % IniWinCount = b" to work rather than being misinterpreted as "if var in", "if var is", and possibly other things. However, "if %var%..." is NOT always an expression because it might be something like: if %A_Index%Array <> unquoted_literal_string
  3300. {
  3301. // To support things like the following, the outermost enclosing parentheses are not removed:
  3302. // if (x < 3) or (x > 6)
  3303. // Also note that although the expression must normally start with an open-parenthesis to be
  3304. // recognized as ACT_IFEXPR, it need not end in a close-paren; e.g. if (x = 1) or !done.
  3305. // If these or any other parentheses are unbalanced, it will caught further below.
  3306. aActionType = ACT_IFEXPR; // Fixed for v1.0.31.01.
  3307. }
  3308. else // Generic or indeterminate IF-statement, so find out what type it is.
  3309. {
  3310. // Skip over the variable name so that the "is" and "is not" operators are properly supported:
  3311. DEFINE_END_FLAGS
  3312. if (operation = StrChrAny(action_args, end_flags))
  3313. operation = omit_leading_whitespace(operation);
  3314. else
  3315. operation = action_args + strlen(action_args); // Point it to the NULL terminator instead.
  3316. // v1.0.42: Fix "If not Installed" not be seen as "If var-named-'not' in MatchList", being
  3317. // careful not to break "If NotInstalled in MatchList". The following are also fixed in
  3318. // a similar way:
  3319. // If not BetweenXXX
  3320. // If not ContainsXXX
  3321. bool first_word_is_not = !strnicmp(action_args, "Not", 3) && strchr(end_flags, action_args[3]);
  3322. switch (*operation)
  3323. {
  3324. case '=': // But don't allow == to be "Equals" since the 2nd '=' might be literal.
  3325. aActionType = ACT_IFEQUAL;
  3326. break;
  3327. case '<':
  3328. switch(operation[1])
  3329. {
  3330. // Note: User can use whitespace to differentiate a literal symbol from
  3331. // part of an operator, e.g. if var1 < = <--- char is literal
  3332. case '=':
  3333. aActionType = ACT_IFLESSOREQUAL;
  3334. operation[1] = ' ';
  3335. break;
  3336. case '>':
  3337. aActionType = ACT_IFNOTEQUAL;
  3338. operation[1] = ' ';
  3339. break;
  3340. default: // i.e. some other character follows '<'
  3341. aActionType = ACT_IFLESS;
  3342. }
  3343. break;
  3344. case '>': // Don't allow >< to be NotEqual since the '<' might be intended as a literal part of an arg.
  3345. if (operation[1] == '=')
  3346. {
  3347. aActionType = ACT_IFGREATEROREQUAL;
  3348. operation[1] = ' '; // Remove it from so that it won't be considered by later parsing.
  3349. }
  3350. else
  3351. aActionType = ACT_IFGREATER;
  3352. break;
  3353. case '!':
  3354. if (operation[1] == '=')
  3355. {
  3356. aActionType = ACT_IFNOTEQUAL;
  3357. operation[1] = ' '; // Remove it from so that it won't be considered by later parsing.
  3358. }
  3359. else
  3360. // To minimize the times where expressions must have an outer set of parentheses,
  3361. // assume all unknown operators are expressions, e.g. "if !var"
  3362. aActionType = ACT_IFEXPR;
  3363. break;
  3364. case 'b': // "Between"
  3365. case 'B':
  3366. // Must fall back to ACT_IFEXPR, otherwise "if not var_name_beginning_with_b" is a syntax error.
  3367. if (first_word_is_not || strnicmp(operation, "between", 7))
  3368. aActionType = ACT_IFEXPR;
  3369. else
  3370. {
  3371. aActionType = ACT_IFBETWEEN;
  3372. // Set things up to be parsed as args further down. A delimiter is inserted later below:
  3373. memset(operation, ' ', 7);
  3374. }
  3375. break;
  3376. case 'c': // "Contains"
  3377. case 'C':
  3378. // Must fall back to ACT_IFEXPR, otherwise "if not var_name_beginning_with_c" is a syntax error.
  3379. if (first_word_is_not || strnicmp(operation, "contains", 8))
  3380. aActionType = ACT_IFEXPR;
  3381. else
  3382. {
  3383. aActionType = ACT_IFCONTAINS;
  3384. // Set things up to be parsed as args further down. A delimiter is inserted later below:
  3385. memset(operation, ' ', 8);
  3386. }
  3387. break;
  3388. case 'i': // "is" or "is not"
  3389. case 'I':
  3390. switch (toupper(operation[1]))
  3391. {
  3392. case 's': // "IS"
  3393. case 'S':
  3394. if (first_word_is_not) // v1.0.45: Had forgotten to fix this one with the others,
  3395. aActionType = ACT_IFEXPR; // so now "if not is_something" and "if not is_something()" work.
  3396. else
  3397. {
  3398. next_word = omit_leading_whitespace(operation + 2);
  3399. if (strnicmp(next_word, "not", 3)) // No need to check for whitespace after the word "not" because things like "if var is notxxx" are never valid.
  3400. aActionType = ACT_IFIS;
  3401. else
  3402. {
  3403. aActionType = ACT_IFISNOT;
  3404. // Remove the word "not" to set things up to be parsed as args further down.
  3405. memset(next_word, ' ', 3);
  3406. }
  3407. operation[1] = ' '; // Remove the 'S' in "IS". 'I' is replaced with ',' later below.
  3408. }
  3409. break;
  3410. case 'n': // "IN"
  3411. case 'N':
  3412. if (first_word_is_not)
  3413. aActionType = ACT_IFEXPR;
  3414. else
  3415. {
  3416. aActionType = ACT_IFIN;
  3417. operation[1] = ' '; // Remove the 'N' in "IN". 'I' is replaced with ',' later below.
  3418. }
  3419. break;
  3420. default:
  3421. // v1.0.35.01 It must fall back to ACT_IFEXPR, otherwise "if not var_name_beginning_with_i"
  3422. // is a syntax error.
  3423. aActionType = ACT_IFEXPR;
  3424. } // switch()
  3425. break;
  3426. case 'n': // It's either "not in", "not between", or "not contains"
  3427. case 'N':
  3428. // Must fall back to ACT_IFEXPR, otherwise "if not var_name_beginning_with_n" is a syntax error.
  3429. if (strnicmp(operation, "not", 3) || !IS_SPACE_OR_TAB(operation[3])) // Fix for v1.0.48: Must also check for whitespace after the word "not" to avoid a syntax error for lines like "if not note".
  3430. aActionType = ACT_IFEXPR;
  3431. else
  3432. {
  3433. // Remove the "NOT" separately in case there is more than one space or tab between
  3434. // it and the following word, e.g. "not between":
  3435. memset(operation, ' ', 3);
  3436. next_word = omit_leading_whitespace(operation + 3);
  3437. if (!strnicmp(next_word, "in", 2))
  3438. {
  3439. aActionType = ACT_IFNOTIN;
  3440. memset(next_word, ' ', 2);
  3441. }
  3442. else if (!strnicmp(next_word, "between", 7))
  3443. {
  3444. aActionType = ACT_IFNOTBETWEEN;
  3445. memset(next_word, ' ', 7);
  3446. }
  3447. else if (!strnicmp(next_word, "contains", 8))
  3448. {
  3449. aActionType = ACT_IFNOTCONTAINS;
  3450. memset(next_word, ' ', 8);
  3451. }
  3452. }
  3453. break;
  3454. default: // To minimize the times where expressions must have an outer set of parentheses, assume all unknown operators are expressions.
  3455. aActionType = ACT_IFEXPR;
  3456. } // switch()
  3457. } // Detection of type of IF-statement.
  3458. if (aActionType == ACT_IFEXPR) // There are various ways above for aActionType to become ACT_IFEXPR.
  3459. {
  3460. // Since this is ACT_IFEXPR, action_args is known not to be an empty string, which is relied on below.
  3461. char *action_args_last_char = action_args + strlen(action_args) - 1; // Shouldn't be a whitespace char since those should already have been removed at an earlier stage.
  3462. if (*action_args_last_char == '{') // This is an if-expression statement with an open-brace on the same line.
  3463. {
  3464. *action_args_last_char = '\0';
  3465. rtrim(action_args, action_args_last_char - action_args); // Remove the '{' and all its whitespace from further consideration.
  3466. add_openbrace_afterward = true;
  3467. }
  3468. }
  3469. else // It's a IF-statement, but a traditional/non-expression one.
  3470. {
  3471. // Set things up to be parsed as args later on.
  3472. *operation = g_delimiter;
  3473. if (aActionType == ACT_IFBETWEEN || aActionType == ACT_IFNOTBETWEEN)
  3474. {
  3475. // I decided against the syntax "if var between 3,8" because the gain in simplicity
  3476. // and the small avoidance of ambiguity didn't seem worth the cost in terms of readability.
  3477. for (next_word = operation;;)
  3478. {
  3479. if ( !(next_word = strcasestr(next_word, "and")) )
  3480. return ScriptError("BETWEEN requires the word AND.", aLineText); // Seems too rare a thing to warrant falling back to ACT_IFEXPR for this.
  3481. if (strchr(" \t", *(next_word - 1)) && strchr(" \t", *(next_word + 3)))
  3482. {
  3483. // Since there's a space or tab on both sides, we know this is the correct "and",
  3484. // i.e. not one contained within one of the parameters. Examples:
  3485. // if var between band and cat ; Don't falsely detect "band"
  3486. // if var betwwen Andy and David ; Don't falsely detect "Andy".
  3487. // Replace the word AND with a delimiter so that it will be parsed correctly later:
  3488. *next_word = g_delimiter;
  3489. *(next_word + 1) = ' ';
  3490. *(next_word + 2) = ' ';
  3491. break;
  3492. }
  3493. else
  3494. next_word += 3; // Skip over this false "and".
  3495. } // for()
  3496. } // ACT_IFBETWEEN
  3497. } // aActionType != ACT_IFEXPR
  3498. }
  3499. else // It isn't an IF-statement, so check for assignments/operators that determine that this line isn't one that starts with a named command.
  3500. {
  3501. //////////////////////////////////////////////////////
  3502. // Detect operators and assignments such as := and +=
  3503. //////////////////////////////////////////////////////
  3504. // This section is done before the section that checks whether action_name is a valid command
  3505. // because it avoids ambiguity in a line such as the following:
  3506. // Input = test ; Would otherwise be confused with the Input command.
  3507. // But there may be times when a line like this is used:
  3508. // MsgBox = ; i.e. the equals is intended to be the first parameter, not an operator.
  3509. // In the above case, the user can provide the optional comma to avoid the ambiguity:
  3510. // MsgBox, =
  3511. char action_args_2nd_char = action_args[1];
  3512. bool convert_pre_inc_or_dec = false; // Set default.
  3513. switch(*action_args)
  3514. {
  3515. case '=': // i.e. var=value (old-style assignment)
  3516. aActionType = ACT_ASSIGN;
  3517. break;
  3518. case ':':
  3519. // v1.0.40: Allow things like "MsgBox :: test" to be valid by insisting that '=' follows ':'.
  3520. if (action_args_2nd_char == '=') // i.e. :=
  3521. aActionType = ACT_ASSIGNEXPR;
  3522. break;
  3523. case '+':
  3524. // Support for ++i (and in the next case, --i). In these cases, action_name must be either
  3525. // "+" or "-", and the first character of action_args must match it.
  3526. if ((convert_pre_inc_or_dec = action_name[0] == '+' && !action_name[1]) // i.e. the pre-increment operator; e.g. ++index.
  3527. || action_args_2nd_char == '=') // i.e. x+=y (by contrast, post-increment is recognized only after we check for a command name to cut down on ambiguity).
  3528. aActionType = ACT_ADD;
  3529. break;
  3530. case '-':
  3531. // Do a complete validation/recognition of the operator to allow a line such as the following,
  3532. // which omits the first optional comma, to still be recognized as a command rather than a
  3533. // variable-with-operator:
  3534. // SetBatchLines -1
  3535. if ((convert_pre_inc_or_dec = action_name[0] == '-' && !action_name[1]) // i.e. the pre-decrement operator; e.g. --index.
  3536. || action_args_2nd_char == '=') // i.e. x-=y (by contrast, post-decrement is recognized only after we check for a command name to cut down on ambiguity).
  3537. aActionType = ACT_SUB;
  3538. break;
  3539. case '*':
  3540. if (action_args_2nd_char == '=') // i.e. *=
  3541. aActionType = ACT_MULT;
  3542. break;
  3543. case '/':
  3544. if (action_args_2nd_char == '=') // i.e. /=
  3545. aActionType = ACT_DIV;
  3546. // ACT_DIV is different than //= and // because ACT_DIV supports floating point inputs by yielding
  3547. // a floating point result (i.e. it doesn't Floor() the result when the inputs are floats).
  3548. else if (action_args_2nd_char == '/' && action_args[2] == '=') // i.e. //=
  3549. aActionType = ACT_EXPRESSION; // Mark this line as a stand-alone expression.
  3550. break;
  3551. case '.':
  3552. case '|':
  3553. case '&':
  3554. case '^':
  3555. if (action_args_2nd_char == '=') // i.e. .= and |= and &= and ^=
  3556. aActionType = ACT_EXPRESSION; // Mark this line as a stand-alone expression.
  3557. break;
  3558. //case '?': Stand-alone ternary such as true ? fn1() : fn2(). These are rare so are
  3559. // checked later, only after action_name has been checked to see if it's a valid command.
  3560. case '>':
  3561. case '<':
  3562. if (action_args_2nd_char == *action_args && action_args[2] == '=') // i.e. >>= and <<=
  3563. aActionType = ACT_EXPRESSION; // Mark this line as a stand-alone expression.
  3564. break;
  3565. //default: Leave aActionType set to ACT_INVALID. This also covers case '\0' in case that's possible.
  3566. } // switch()
  3567. if (aActionType) // An assignment or other type of action was discovered above.
  3568. {
  3569. if (convert_pre_inc_or_dec) // Set up pre-ops like ++index and --index to be parsed properly later.
  3570. {
  3571. // The following converts:
  3572. // ++x -> EnvAdd x,1 (not really "EnvAdd" per se; but ACT_ADD).
  3573. // Set action_args to be the word that occurs after the ++ or --:
  3574. action_args = omit_leading_whitespace(++action_args); // Though there generally isn't any.
  3575. if (StrChrAny(action_args, EXPR_ALL_SYMBOLS ".")) // Support things like ++Var ? f1() : f2() and ++Var /= 5. Don't need strstr(action_args, " ?") because the search already looks for ':'.
  3576. aActionType = ACT_EXPRESSION; // Mark this line as a stand-alone expression.
  3577. else
  3578. {
  3579. // Set up aLineText and action_args to be parsed later on as a list of two parameters:
  3580. // The variable name followed by the amount to be added or subtracted (e.g. "ScriptVar, 1").
  3581. // We're not changing the length of aLineText by doing this, so it should be large enough:
  3582. size_t new_length = strlen(action_args);
  3583. // Since action_args is just a pointer into the aLineText buffer (which caller has ensured
  3584. // is modifiable), use memmove() so that overlapping source & dest are properly handled:
  3585. memmove(aLineText, action_args, new_length + 1); // +1 to include the zero terminator.
  3586. // Append the second param, which is just "1" since the ++ and -- only inc/dec by 1:
  3587. aLineText[new_length++] = g_delimiter;
  3588. aLineText[new_length++] = '1';
  3589. aLineText[new_length] = '\0';
  3590. }
  3591. }
  3592. else if (aActionType != ACT_EXPRESSION) // i.e. it's ACT_ASSIGN/ASSIGNEXPR/ADD/SUB/MULT/DIV
  3593. {
  3594. if (aActionType != ACT_ASSIGN) // i.e. it's ACT_ASSIGNEXPR/ADD/SUB/MULT/DIV
  3595. {
  3596. // Find the first non-function comma, which in the case of ACT_ADD/SUB can be
  3597. // either a statement-separator comma (expression) or the time units arg.
  3598. // Reasons for this:
  3599. // 1) ACT_ADD/SUB: Need to distinguish compound statements from date/time math;
  3600. // e.g. "x+=1, y+=2" should be marked as a stand-alone expression, not date math.
  3601. // 2) ACT_ASSIGNEXPR/MULT/DIV (and ACT_ADD/SUB for that matter): Need to make
  3602. // comma-separated sub-expressions into one big ACT_EXPRESSION so that the
  3603. // leftmost sub-expression will get evaluated prior to the others (for consistency
  3604. // and as documented). However, this has some side-effects, such as making
  3605. // the leftmost /= operator into true division rather than ENV_DIV behavior,
  3606. // and treating blanks as errors in math expressions when otherwise ENV_MULT
  3607. // would treat them as zero.
  3608. // ALSO: ACT_ASSIGNEXPR/ADD/SUB/MULT/DIV are made into ACT_EXPRESSION *only* when multi-
  3609. // statement commas are present because the following legacy behaviors must be retained:
  3610. // 1) Math treatment of blanks as zero in ACT_ADD/SUB/etc.
  3611. // 2) EnvDiv's special behavior, which is different than both true divide and floor divide.
  3612. // 3) Possibly add/sub's date/time math.
  3613. // 4) Maybe obsolete: For performance, don't want trivial assignments to become ACT_EXPRESSION.
  3614. char *cp;
  3615. for (in_quotes = false, open_parens = 0, cp = action_args + 2; *cp; ++cp)
  3616. {
  3617. switch (*cp)
  3618. {
  3619. case '"': // This is whole section similar to another one later below, so see it for comments.
  3620. in_quotes = !in_quotes;
  3621. break;
  3622. case '(':
  3623. if (!in_quotes) // Literal parentheses inside a quoted string should not be counted for this purpose.
  3624. ++open_parens;
  3625. break;
  3626. case ')':
  3627. if (!in_quotes)
  3628. --open_parens;
  3629. break;
  3630. }
  3631. if (*cp == g_delimiter && !in_quotes && open_parens < 1) // A delimiting comma other than one in a sub-statement or function. Shouldn't need to worry about unquoted escaped commas since they don't make sense with += and -=.
  3632. {
  3633. if (aActionType == ACT_ADD || aActionType == ACT_SUB)
  3634. {
  3635. cp = omit_leading_whitespace(cp + 1);
  3636. if (StrChrAny(cp, EXPR_ALL_SYMBOLS ".")) // Don't need strstr(cp, " ?") because the search already looks for ':'.
  3637. aActionType = ACT_EXPRESSION; // It's clearly an expression not a word like Days or %VarContainingTheWordDays%.
  3638. //else it's probably date/time math, so leave it as-is.
  3639. }
  3640. else // ACT_ASSIGNEXPR/MULT/DIV, for which any non-function comma qualifies it as multi-statement.
  3641. aActionType = ACT_EXPRESSION;
  3642. break;
  3643. }
  3644. }
  3645. }
  3646. if (aActionType != ACT_EXPRESSION) // The above didn't make it a stand-alone expression.
  3647. {
  3648. // The following converts:
  3649. // x+=2 -> ACT_ADD x, 2.
  3650. // x:=2 -> ACT_ASSIGNEXPR, x, 2
  3651. // etc.
  3652. // But post-inc/dec are recognized only after we check for a command name to cut down on ambiguity
  3653. *action_args = g_delimiter; // Replace the =,+,-,:,*,/ with a delimiter for later parsing.
  3654. if (aActionType != ACT_ASSIGN) // i.e. it's not just a plain equal-sign (which has no 2nd char).
  3655. action_args[1] = ' '; // Remove the "=" from consideration.
  3656. }
  3657. }
  3658. //else it's already an isolated expression, so no changes are desired.
  3659. action_args = aLineText; // Since this is an assignment and/or expression, use the line's full text for later parsing.
  3660. } // if (aActionType)
  3661. } // Handling of assignments and other operators.
  3662. }
  3663. //else aActionType was already determined by the caller.
  3664. // Now the above has ensured that action_args is the first parameter itself, or empty-string if none.
  3665. // If action_args now starts with a delimiter, it means that the first param is blank/empty.
  3666. if (!aActionType && !aOldActionType) // Caller nor logic above has yet determined the action.
  3667. if ( !(aActionType = ConvertActionType(action_name)) ) // Is this line a command?
  3668. aOldActionType = ConvertOldActionType(action_name); // If not, is it an old-command?
  3669. if (!aActionType && !aOldActionType) // Didn't find any action or command in this line.
  3670. {
  3671. // v1.0.41: Support one-true brace style even if there's no space, but make it strict so that
  3672. // things like "Loop{ string" are reported as errors (in case user intended a file-pattern loop).
  3673. if (!stricmp(action_name, "Loop{") && !*action_args)
  3674. {
  3675. aActionType = ACT_LOOP;
  3676. add_openbrace_afterward = true;
  3677. }
  3678. else if (*action_args == '?' && IS_SPACE_OR_TAB(action_args[1]) // '?' currently requires a trailing space or tab because variable names can contain '?' (except '?' by itself). For simplicty, no NBSP check.
  3679. || strchr(EXPR_ALL_SYMBOLS ".", *action_args))
  3680. {
  3681. char *question_mark;
  3682. if ((*action_args == '+' || *action_args == '-') && action_args[1] == *action_args) // Post-inc/dec. See comments further below.
  3683. {
  3684. if (action_args[2]) // i.e. if the ++ and -- isn't the last thing; e.g. x++ ? fn1() : fn2() ... Var++ //= 2
  3685. aActionType = ACT_EXPRESSION; // Mark this line as a stand-alone expression.
  3686. else
  3687. {
  3688. // The logic here allows things like IfWinActive-- to be seen as commands even without
  3689. // a space before the -- or ++. For backward compatibility and code simplicity, it seems
  3690. // best to keep that behavior rather than distinguishing between Command-- and Command --.
  3691. // In any case, "Command --" should continue to be seen as a command regardless of what
  3692. // changes are ever made. That's why this section occurs below the command-name lookup.
  3693. // The following converts x++ to "ACT_ADD x,1".
  3694. aActionType = (*action_args == '+') ? ACT_ADD : ACT_SUB;
  3695. *action_args = g_delimiter;
  3696. action_args[1] = '1';
  3697. }
  3698. action_args = aLineText; // Since this is an assignment and/or expression, use the line's full text for later parsing.
  3699. }
  3700. else if (*action_args == '?' // Don't need a leading space if first char is '?' (though should have a trailing, but for simplicity it isn't checked).
  3701. || (question_mark = strstr(action_args, " ? ")) && strchr(question_mark, ':')) // Rough check (see comments below). Relies on short-circuit boolean order.
  3702. {
  3703. // To avoid hindering load-time error detection such as misspelled command names, allow stand-alone
  3704. // expressions only for things that can produce a side-effect (currently only ternaries like
  3705. // the ones mentioned later below need to be checked since the following other things were
  3706. // previously recognized as ACT_EXPRESSION if appropriate: function-calls, post- and
  3707. // pre-inc/dec (++/--), and assignment operators like := += *= (though these don't necessarily
  3708. // need to be ACT_EXPRESSION to support multi-statement; they can be ACT_ASSIGNEXPR, ACT_ADD, etc.
  3709. // and still support comma-separated statements.
  3710. // Stand-alone ternaries are checked for here rather than earlier to allow a command name
  3711. // (of present) to take precedence (since stand-alone ternaries seem much rarer than
  3712. // "Command ? something" such as "MsgBox ? something". Could also check for a colon somewhere
  3713. // to the right if further ambiguity-resolution is ever needed. Also, a stand-alone ternary
  3714. // should have at least one function-call and/or assignment; otherwise it would serve no purpose.
  3715. // A line may contain a stand-alone ternary operator to call functions that have side-effects
  3716. // or perform assignments. For example:
  3717. // IsDone ? fn1() : fn2()
  3718. // 3 > 2 ? x:=1 : y:=1
  3719. // (3 > 2) ... not supported due to overlap with continuation sections.
  3720. aActionType = ACT_EXPRESSION; // Mark this line as a stand-alone expression.
  3721. action_args = aLineText; // Since this is an assignment and/or expression, use the line's full text for later parsing.
  3722. }
  3723. //else leave it as an unknown action to avoid hindering load-time error detection.
  3724. // In other words, don't be too permissive about what gets marked as a stand-alone expression.
  3725. }
  3726. if (!aActionType) // Above still didn't find a valid action (i.e. check aActionType again in case the above changed it).
  3727. {
  3728. if (*action_args == '(') // v1.0.46.11: Recognize as multi-statements that start with a function, like "fn(), x:=4". v1.0.47.03: Removed the following check to allow a close-brace to be followed by a comma-less function-call: strchr(action_args, g_delimiter).
  3729. {
  3730. aActionType = ACT_EXPRESSION; // Mark this line as a stand-alone expression.
  3731. action_args = aLineText; // Since this is a function-call followed by a comma and some other expression, use the line's full text for later parsing.
  3732. }
  3733. else
  3734. // v1.0.40: Give a more specific error message now now that hotkeys can make it here due to
  3735. // the change that avoids the need to escape double-colons:
  3736. return ScriptError(strstr(aLineText, HOTKEY_FLAG) ? "Invalid hotkey." : ERR_UNRECOGNIZED_ACTION, aLineText);
  3737. }
  3738. }
  3739. Action &this_action = aActionType ? g_act[aActionType] : g_old_act[aOldActionType];
  3740. //////////////////////////////////////////////////////////////////////////////////////////////
  3741. // Handle escaped-sequences (escaped delimiters and all others except variable deref symbols).
  3742. // This section must occur after all other changes to the pointer value action_args have
  3743. // occurred above.
  3744. //////////////////////////////////////////////////////////////////////////////////////////////
  3745. // The size of this relies on the fact that caller made sure that aLineText isn't
  3746. // longer than LINE_SIZE. Also, it seems safer to use char rather than bool, even
  3747. // though on most compilers they're the same size. Char is always of size 1, but bool
  3748. // can be bigger depending on platform/compiler:
  3749. char literal_map[LINE_SIZE];
  3750. ZeroMemory(literal_map, sizeof(literal_map)); // Must be fully zeroed for this purpose.
  3751. if (aLiteralMap)
  3752. {
  3753. // Since literal map is NOT a string, just an array of char values, be sure to
  3754. // use memcpy() vs. strcpy() on it. Also, caller's aLiteralMap starts at aEndMarker,
  3755. // so adjust it so that it starts at the newly found position of action_args instead:
  3756. int map_offset = (int)(action_args - end_marker); // end_marker is known not to be NULL when aLiteralMap is non-NULL.
  3757. int map_length = (int)(aLiteralMapLength - map_offset);
  3758. if (map_length > 0)
  3759. memcpy(literal_map, aLiteralMap + map_offset, map_length);
  3760. }
  3761. else
  3762. {
  3763. // Resolve escaped sequences and make a map of which characters in the string should
  3764. // be interpreted literally rather than as their native function. In other words,
  3765. // convert any escape sequences in order from left to right (this order is important,
  3766. // e.g. ``% should evaluate to `g_DerefChar not `LITERAL_PERCENT. This part must be
  3767. // done *after* checking for comment-flags that appear to the right of a valid line, above.
  3768. // How literal comment-flags (e.g. semicolons) work:
  3769. //string1; string2 <-- not a problem since string2 won't be considered a comment by the above.
  3770. //string1 ; string2 <-- this would be a user mistake if string2 wasn't supposed to be a comment.
  3771. //string1 `; string 2 <-- since esc seq. is resolved *after* checking for comments, this behaves as intended.
  3772. // Current limitation: a comment-flag longer than 1 can't be escaped, so if "//" were used,
  3773. // as a comment flag, it could never have whitespace to the left of it if it were meant to be literal.
  3774. // Note: This section resolves all escape sequences except those involving g_DerefChar, which
  3775. // are handled by a later section.
  3776. char c;
  3777. int i;
  3778. for (i = 0; ; ++i) // Increment to skip over the symbol just found by the inner for().
  3779. {
  3780. for (; action_args[i] && action_args[i] != g_EscapeChar; ++i); // Find the next escape char.
  3781. if (!action_args[i]) // end of string.
  3782. break;
  3783. c = action_args[i + 1];
  3784. switch (c)
  3785. {
  3786. // Only lowercase is recognized for these:
  3787. case 'a': action_args[i + 1] = '\a'; break; // alert (bell) character
  3788. case 'b': action_args[i + 1] = '\b'; break; // backspace
  3789. case 'f': action_args[i + 1] = '\f'; break; // formfeed
  3790. case 'n': action_args[i + 1] = '\n'; break; // newline
  3791. case 'r': action_args[i + 1] = '\r'; break; // carriage return
  3792. case 't': action_args[i + 1] = '\t'; break; // horizontal tab
  3793. case 'v': action_args[i + 1] = '\v'; break; // vertical tab
  3794. }
  3795. // Replace escape-sequence with its single-char value. This is done event if the pair isn't
  3796. // a recognizable escape sequence (e.g. `? becomes ?), which is the Microsoft approach
  3797. // and might not be a bad way of handing things. There are some exceptions, however.
  3798. // The first of these exceptions (g_DerefChar) is mandatory because that char must be
  3799. // handled at a later stage or escaped g_DerefChars won't work right. The others are
  3800. // questionable, and might be worth further consideration. UPDATE: g_DerefChar is now
  3801. // done here because otherwise, examples such as this fail:
  3802. // - The escape char is backslash.
  3803. // - any instances of \\%, such as c:\\%var% , will not work because the first escape
  3804. // sequence (\\) is resolved to a single literal backslash. But then when \% is encountered
  3805. // by the section that resolves escape sequences for g_DerefChar, the backslash is seen
  3806. // as an escape char rather than a literal backslash, which is not correct. Thus, we
  3807. // resolve all escapes sequences HERE in one go, from left to right.
  3808. // AutoIt2 definitely treats an escape char that occurs at the very end of
  3809. // a line as literal. It seems best to also do it for these other cases too.
  3810. // UPDATE: I cannot reproduce the above behavior in AutoIt2. Maybe it only
  3811. // does it for some commands or maybe I was mistaken. So for now, this part
  3812. // is disabled:
  3813. //if (c == '\0' || c == ' ' || c == '\t')
  3814. // literal_map[i] = 1; // In the map, mark this char as literal.
  3815. //else
  3816. {
  3817. // So these are also done as well, and don't need an explicit check:
  3818. // g_EscapeChar , g_delimiter , (when g_CommentFlagLength > 1 ??): *g_CommentFlag
  3819. // Below has a final +1 to include the terminator:
  3820. MoveMemory(action_args + i, action_args + i + 1, strlen(action_args + i + 1) + 1);
  3821. literal_map[i] = 1; // In the map, mark this char as literal.
  3822. }
  3823. // else: Do nothing, even if the value is zero (the string's terminator).
  3824. }
  3825. }
  3826. ////////////////////////////////////////////////////////////////////////////////////////
  3827. // Do some special preparsing of the MsgBox command, since it is so frequently used and
  3828. // it is also the source of problem areas going from AutoIt2 to 3 and also due to the
  3829. // new numeric parameter at the end. Whenever possible, we want to avoid the need for
  3830. // the user to have to escape commas that are intended to be literal.
  3831. ///////////////////////////////////////////////////////////////////////////////////////
  3832. int mark, max_params_override = 0; // Set default.
  3833. if (aActionType == ACT_MSGBOX)
  3834. {
  3835. // First find out how many non-literal (non-escaped) delimiters are present.
  3836. // Use a high maximum so that we can almost always find and analyze the command's
  3837. // last apparent parameter. This helps error-checking be more informative in a
  3838. // case where the command specifies a timeout as its last param but it's next-to-last
  3839. // param contains delimiters that the user forgot to escape. In other words, this
  3840. // helps detect more often when the user is trying to use the timeout feature.
  3841. // If this weren't done, the command would more often forgive improper syntax
  3842. // and not report a load-time error, even though it's pretty obvious that a load-time
  3843. // error should have been reported:
  3844. #define MAX_MSGBOX_DELIMITERS 20
  3845. char *delimiter[MAX_MSGBOX_DELIMITERS];
  3846. int delimiter_count;
  3847. for (mark = delimiter_count = 0; action_args[mark] && delimiter_count < MAX_MSGBOX_DELIMITERS;)
  3848. {
  3849. for (; action_args[mark]; ++mark)
  3850. if (action_args[mark] == g_delimiter && !literal_map[mark]) // Match found: a non-literal delimiter.
  3851. {
  3852. delimiter[delimiter_count++] = action_args + mark;
  3853. ++mark; // Skip over this delimiter for the next iteration of the outer loop.
  3854. break;
  3855. }
  3856. }
  3857. // If it has only 1 arg (i.e. 0 delimiters within the arg list) no override is needed.
  3858. // Otherwise do more checking:
  3859. if (delimiter_count)
  3860. {
  3861. char *cp;
  3862. // If the first apparent arg is not a non-blank pure number or there are apparently
  3863. // only 2 args present (i.e. 1 delimiter in the arg list), assume the command is being
  3864. // used in its 1-parameter mode:
  3865. if (delimiter_count <= 1) // 2 parameters or less.
  3866. // Force it to be 1-param mode. In other words, we want to make MsgBox a very forgiving
  3867. // command and have it rarely if ever report syntax errors:
  3868. max_params_override = 1;
  3869. else // It has more than 3 apparent params, but is the first param even numeric?
  3870. {
  3871. *delimiter[0] = '\0'; // Temporarily terminate action_args at the first delimiter.
  3872. // Note: If it's a number inside a variable reference, it's still considered 1-parameter
  3873. // mode to avoid ambiguity (unlike the new deref checking for param #4 mentioned below,
  3874. // there seems to be too much ambiguity in this case to justify trying to figure out
  3875. // if the first parameter is a pure deref, and thus that the command should use
  3876. // 3-param or 4-param mode instead).
  3877. if (!IsPureNumeric(action_args)) // No floats allowed. Allow all-whitespace for aut2 compatibility.
  3878. max_params_override = 1;
  3879. *delimiter[0] = g_delimiter; // Restore the string.
  3880. if (!max_params_override)
  3881. {
  3882. // IMPORATANT: The MsgBox cmd effectively has 3 parameter modes:
  3883. // 1-parameter (where all commas in the 1st parameter are automatically literal)
  3884. // 3-parameter (where all commas in the 3rd parameter are automatically literal)
  3885. // 4-parameter (whether the 4th parameter is the timeout value)
  3886. // Thus, the below must be done in a way that recognizes & supports all 3 modes.
  3887. // The above has determined that the cmd isn't in 1-parameter mode.
  3888. // If at this point it has exactly 3 apparent params, allow the command to be
  3889. // processed normally without an override. Otherwise, do more checking:
  3890. if (delimiter_count == 3) // i.e. 3 delimiters, which means 4 params.
  3891. {
  3892. // If the 4th parameter isn't blank or pure numeric, assume the user didn't
  3893. // intend it to be the MsgBox timeout (since that feature is rarely used),
  3894. // instead intending it to be part of parameter #3.
  3895. if (!IsPureNumeric(delimiter[2] + 1, false, true, true))
  3896. {
  3897. // Not blank and not a int or float. Update for v1.0.20: Check if it's a
  3898. // single deref. If so, assume that deref contains the timeout and thus
  3899. // 4-param mode is in effect. This allows the timeout to be contained in
  3900. // a variable, which was requested by one user:
  3901. cp = omit_leading_whitespace(delimiter[2] + 1);
  3902. // Relies on short-circuit boolean order:
  3903. if (*cp != g_DerefChar || literal_map[cp - action_args]) // not a proper deref char.
  3904. max_params_override = 3;
  3905. // else since it does start with a real deref symbol, it must end with one otherwise
  3906. // that will be caught later on as a syntax error anyway. Therefore, don't override
  3907. // max_params, just let it be parsed as 4 parameters.
  3908. }
  3909. // If it has more than 4 params or it has exactly 4 but the 4th isn't blank,
  3910. // pure numeric, or a deref: assume it's being used in 3-parameter mode and
  3911. // that all the other delimiters were intended to be literal.
  3912. }
  3913. else if (delimiter_count > 3) // i.e. 4 or more delimiters, which means 5 or more params.
  3914. {
  3915. // v1.0.48: This section extends smart comma handling so that if parameter #3 (Text)
  3916. // is an expression, any commas in it won't interfere with the Timeout parameter.
  3917. // For example, the timeout parameter below should work now:
  3918. // MsgBox 0, Title, % Func(x,y), 1
  3919. //
  3920. // If the "Text" parameter is an expression then commas inside it can't be intended to
  3921. // be literal/displayed by the user unless they're enclosed in quotes; but in that case,
  3922. // the smartness below isn't needed because it's provided by the parameter-parsing logic
  3923. // in a later section. So in that case it seems safe to avoid setting max_params_override,
  3924. // which fixes examples like the one above. The code further below does this.
  3925. //
  3926. // By contrast, fixing the second parameter (Title) in a similar way would be more
  3927. // difficult and/or would be more likely to break existing scripts. For example if "title"
  3928. // is an expression but "text" is NOT an expression, there might be some commas in "text"
  3929. // that are currently handled as smart/auto-literal, and those cases should be preserved
  3930. // for backward compatibility.
  3931. //
  3932. // If expressions in the "title" parameter ever are fixed to not interfere with the
  3933. // Timeout parameter, perhaps the best way to do it would be to verify that it's an
  3934. // expression, then skip over any commas that are enclosed in quotes or parentheses so that
  3935. // the "real" commas can be counted and used by the rest of the smart-comma logic.
  3936. //
  3937. // For the section below, see comments at the similar code section above:
  3938. cp = omit_leading_whitespace(delimiter[1] + 1); // Parameter #3, the "text" parameter.
  3939. if ( *cp != g_DerefChar || literal_map[cp - action_args] // not a proper deref char...
  3940. || !IS_SPACE_OR_TAB(cp[1]) ) // ...or it's not followed by a space or tab, so it isn't "% ".
  3941. // Since it has too many delimiters to be 4-param mode and since there is no "% "
  3942. // expression present, assume it's 3-param mode so that non-escaped commas in
  3943. // parameters 4 and beyond will be all treated as strings that are part of parameter #3.
  3944. max_params_override = 3;
  3945. }
  3946. //else if 3 params or less: Don't override via max_params_override, just parse it normally.
  3947. }
  3948. }
  3949. }
  3950. } // end of special handling for MsgBox.
  3951. /////////////////////////////////////////////////////////////
  3952. // Parse the parameter string into a list of separate params.
  3953. /////////////////////////////////////////////////////////////
  3954. // MaxParams has already been verified as being <= MAX_ARGS.
  3955. // Any g_delimiter-delimited items beyond MaxParams will be included in a lump inside the last param:
  3956. int nArgs, nArgs_plus_one;
  3957. char *arg[MAX_ARGS], *arg_map[MAX_ARGS];
  3958. ActionTypeType subaction_type = ACT_INVALID; // Must init these.
  3959. ActionTypeType suboldaction_type = OLD_INVALID;
  3960. char subaction_name[MAX_VAR_NAME_LENGTH + 1], *subaction_end_marker = NULL, *subaction_start = NULL;
  3961. int max_params = max_params_override ? max_params_override
  3962. : (mIsAutoIt2 ? (this_action.MaxParamsAu2WithHighBit & 0x7F) // 0x7F removes the high-bit from consideration; that bit is used for an unrelated purpose.
  3963. : this_action.MaxParams);
  3964. int max_params_minus_one = max_params - 1;
  3965. bool is_expression;
  3966. ActionTypeType *np;
  3967. for (nArgs = mark = 0; action_args[mark] && nArgs < max_params; ++nArgs)
  3968. {
  3969. if (nArgs == 2) // i.e. the 3rd arg is about to be added.
  3970. {
  3971. switch (aActionType) // will be ACT_INVALID if this_action is an old-style command.
  3972. {
  3973. case ACT_IFWINEXIST:
  3974. case ACT_IFWINNOTEXIST:
  3975. case ACT_IFWINACTIVE:
  3976. case ACT_IFWINNOTACTIVE:
  3977. subaction_start = action_args + mark;
  3978. if (subaction_end_marker = ParseActionType(subaction_name, subaction_start, false))
  3979. if ( !(subaction_type = ConvertActionType(subaction_name)) )
  3980. suboldaction_type = ConvertOldActionType(subaction_name);
  3981. break;
  3982. }
  3983. if (subaction_type || suboldaction_type)
  3984. // A valid command was found (i.e. AutoIt2-style) in place of this commands Exclude Title
  3985. // parameter, so don't add this item as a param to the command.
  3986. break;
  3987. }
  3988. arg[nArgs] = action_args + mark;
  3989. arg_map[nArgs] = literal_map + mark;
  3990. if (nArgs == max_params_minus_one)
  3991. {
  3992. // Don't terminate the last param, just put all the rest of the line
  3993. // into it. This avoids the need for the user to escape any commas
  3994. // that may appear in the last param. i.e. any commas beyond this
  3995. // point can't be delimiters because we've already reached MaxArgs
  3996. // for this command:
  3997. ++nArgs;
  3998. break;
  3999. }
  4000. // The above does not need the in_quotes and in_parens checks because commas in the last arg
  4001. // are always literal, so there's no problem even in expressions.
  4002. // The following implements the "% " prefix as a means of forcing an expression:
  4003. is_expression = *arg[nArgs] == g_DerefChar && !*arg_map[nArgs] // It's a non-literal deref character.
  4004. && IS_SPACE_OR_TAB(arg[nArgs][1]); // Followed by a space or tab.
  4005. // Find the end of the above arg:
  4006. for (in_quotes = false, open_parens = 0; action_args[mark]; ++mark)
  4007. {
  4008. switch (action_args[mark])
  4009. {
  4010. case '"':
  4011. // The simple method below is sufficient for our purpose even if a quoted string contains
  4012. // pairs of double-quotes to represent a single literal quote, e.g. "quoted ""word""".
  4013. // In other words, it relies on the fact that there must be an even number of quotes
  4014. // inside any mandatory-numeric arg that is an expression such as x=="red,blue"
  4015. in_quotes = !in_quotes;
  4016. break;
  4017. case '(':
  4018. if (!in_quotes) // Literal parentheses inside a quoted string should not be counted for this purpose.
  4019. ++open_parens;
  4020. break;
  4021. case ')':
  4022. if (!in_quotes)
  4023. --open_parens;
  4024. break;
  4025. }
  4026. if (action_args[mark] == g_delimiter && !literal_map[mark]) // A non-literal delimiter (unless its within double-quotes of a mandatory-numeric arg) is a match.
  4027. {
  4028. // If we're inside a pair of quotes or parentheses and this arg is known to be an expression, this
  4029. // delimiter is part this arg and thus not to be used as a delimiter between command args:
  4030. if (in_quotes || open_parens > 0)
  4031. {
  4032. if (is_expression)
  4033. continue;
  4034. if (aActionType == ACT_TRANSFORM && (nArgs == 2 || nArgs == 3)) // i.e. the 3rd or 4th arg is about to be added.
  4035. {
  4036. // Somewhat inefficient in the case where it has to be called for both Arg#2 and Arg#3,
  4037. // but that is pretty rare. Overall, expressions and quoted strings in these args
  4038. // is rare too, so the inefficiency of redundant calls to ConvertTransformCmd() is
  4039. // very small on average, and seems worth the benefit in terms of code simplification.
  4040. // Note that the following might return TRANS_CMD_INVALID just because the sub-command
  4041. // is containined in a variable reference. That is why TRANS_CMD_INVALID does not
  4042. // produce an error at this stage, but only later when the line has been constructed
  4043. // far enough to call ArgHasDeref():
  4044. // i.e. Not the first param, only the third and fourth, which currently are either both numeric or both non-numeric for all cases.
  4045. switch(Line::ConvertTransformCmd(arg[1])) // arg[1] is the second arg.
  4046. {
  4047. // See comment above for why TRANS_CMD_INVALID isn't yet reported as an error:
  4048. #define TRANSFORM_NON_EXPRESSION_CASES \
  4049. case TRANS_CMD_INVALID:\
  4050. case TRANS_CMD_ASC:\
  4051. case TRANS_CMD_UNICODE:\
  4052. case TRANS_CMD_DEREF:\
  4053. case TRANS_CMD_HTML:\
  4054. break; // Do nothing. Leave this_new_arg.is_expression set to its default of false.
  4055. TRANSFORM_NON_EXPRESSION_CASES
  4056. default:
  4057. // For all other sub-commands, Arg #3 and #4 are expression-capable. It doesn't
  4058. // seem necessary to call LegacyArgIsExpression() because the mere fact that
  4059. // we're inside a pair of quotes or parentheses seems enough to indicate that this
  4060. // really is an expression.
  4061. continue;
  4062. }
  4063. }
  4064. // v1.0.43.07: Fixed below to use this_action instead of g_act[aActionType] so that the
  4065. // numeric params of legacy commands like EnvAdd/Sub/LeftClick can be detected. Without
  4066. // this fix, the last comma in a line like "EnvSub, var, Add(2, 3)" is seen as a parameter
  4067. // delimiter, which causes a loadtime syntax error.
  4068. if (np = this_action.NumericParams) // This command has at least one numeric parameter.
  4069. {
  4070. // As of v1.0.25, pure numeric parameters can optionally be numeric expressions, so check for that:
  4071. nArgs_plus_one = nArgs + 1;
  4072. for (; *np; ++np)
  4073. if (*np == nArgs_plus_one) // This arg is enforced to be purely numeric.
  4074. break;
  4075. if (*np) // Match found, so this is a purely numeric arg.
  4076. continue; // This delimiter is disqualified, so look for the next one.
  4077. }
  4078. } // if in quotes or parentheses
  4079. // Since above didn't "continue", this is a real delimiter.
  4080. action_args[mark] = '\0'; // Terminate the previous arg.
  4081. // Trim any whitespace from the previous arg. This operation
  4082. // will not alter the contents of anything beyond action_args[i],
  4083. // so it should be safe. In addition, even though it changes
  4084. // the contents of the arg[nArgs] substring, we don't have to
  4085. // update literal_map because the map is still accurate due
  4086. // to the nature of rtrim). UPDATE: Note that this version
  4087. // of rtrim() specifically avoids trimming newline characters,
  4088. // since the user may have included literal newlines at the end
  4089. // of the string by using an escape sequence:
  4090. rtrim(arg[nArgs]);
  4091. // Omit the leading whitespace from the next arg:
  4092. for (++mark; IS_SPACE_OR_TAB(action_args[mark]); ++mark);
  4093. // Now <mark> marks the end of the string, the start of the next arg,
  4094. // or a delimiter-char (if the next arg is blank).
  4095. break; // Arg was found, so let the outer loop handle it.
  4096. }
  4097. }
  4098. }
  4099. ///////////////////////////////////////////////////////////////////////////////
  4100. // Ensure there are sufficient parameters for this command. Note: If MinParams
  4101. // is greater than 0, the param numbers 1 through MinParams are required to be
  4102. // non-blank.
  4103. ///////////////////////////////////////////////////////////////////////////////
  4104. char error_msg[1024];
  4105. if (nArgs < this_action.MinParams)
  4106. {
  4107. snprintf(error_msg, sizeof(error_msg), "\"%s\" requires at least %d parameter%s."
  4108. , this_action.Name, this_action.MinParams
  4109. , this_action.MinParams > 1 ? "s" : "");
  4110. return ScriptError(error_msg, aLineText);
  4111. }
  4112. for (int i = 0; i < this_action.MinParams; ++i) // It's only safe to do this after the above.
  4113. if (!*arg[i])
  4114. {
  4115. snprintf(error_msg, sizeof(error_msg), "\"%s\" requires that parameter #%u be non-blank."
  4116. , this_action.Name, i + 1);
  4117. return ScriptError(error_msg, aLineText);
  4118. }
  4119. ////////////////////////////////////////////////////////////////////////
  4120. // Handle legacy commands that are supported for backward compatibility.
  4121. ////////////////////////////////////////////////////////////////////////
  4122. if (aOldActionType)
  4123. {
  4124. switch(aOldActionType)
  4125. {
  4126. case OLD_LEFTCLICK:
  4127. case OLD_RIGHTCLICK:
  4128. // Insert an arg at the beginning of the list to indicate the mouse button.
  4129. arg[2] = arg[1]; arg_map[2] = arg_map[1];
  4130. arg[1] = arg[0]; arg_map[1] = arg_map[0];
  4131. arg[0] = aOldActionType == OLD_LEFTCLICK ? "" : "Right"; arg_map[0] = NULL; // "" is treated the same as "Left"
  4132. return AddLine(ACT_MOUSECLICK, arg, ++nArgs, arg_map);
  4133. case OLD_LEFTCLICKDRAG:
  4134. case OLD_RIGHTCLICKDRAG:
  4135. // Insert an arg at the beginning of the list to indicate the mouse button.
  4136. arg[4] = arg[3]; arg_map[4] = arg_map[3]; // Set the 5th arg to be the 4th, etc.
  4137. arg[3] = arg[2]; arg_map[3] = arg_map[2];
  4138. arg[2] = arg[1]; arg_map[2] = arg_map[1];
  4139. arg[1] = arg[0]; arg_map[1] = arg_map[0];
  4140. arg[0] = (aOldActionType == OLD_LEFTCLICKDRAG) ? "Left" : "Right"; arg_map[0] = NULL;
  4141. return AddLine(ACT_MOUSECLICKDRAG, arg, ++nArgs, arg_map);
  4142. case OLD_HIDEAUTOITWIN:
  4143. // This isn't a perfect mapping because the word "on" or "off" might be contained
  4144. // in a variable reference, in which case this conversion will be incorrect.
  4145. // However, variable ref. is exceedingly rare.
  4146. arg[1] = stricmp(arg[0], "On") ? "Icon" : "NoIcon";
  4147. arg[0] = "Tray"; // Assign only after we're done using the old arg[0] value above.
  4148. return AddLine(ACT_MENU, arg, 2, arg_map);
  4149. case OLD_REPEAT:
  4150. if (!AddLine(ACT_REPEAT, arg, nArgs, arg_map))
  4151. return FAIL;
  4152. // For simplicity, always enclose repeat-loop's contents in in a block rather
  4153. // than trying to detect if it has only one line:
  4154. return AddLine(ACT_BLOCK_BEGIN);
  4155. case OLD_ENDREPEAT:
  4156. return AddLine(ACT_BLOCK_END);
  4157. case OLD_WINGETACTIVETITLE:
  4158. arg[nArgs] = "A"; arg_map[nArgs] = NULL; // "A" signifies the active window.
  4159. ++nArgs;
  4160. return AddLine(ACT_WINGETTITLE, arg, nArgs, arg_map);
  4161. case OLD_WINGETACTIVESTATS:
  4162. {
  4163. // Convert OLD_WINGETACTIVESTATS into *two* new commands:
  4164. // Command #1: WinGetTitle, OutputVar, A
  4165. char *width = arg[1]; // Temporary placeholder.
  4166. arg[1] = "A"; arg_map[1] = NULL; // Signifies the active window.
  4167. if (!AddLine(ACT_WINGETTITLE, arg, 2, arg_map))
  4168. return FAIL;
  4169. // Command #2: WinGetPos, XPos, YPos, Width, Height, A
  4170. // Reassign args in the new command's ordering. These lines must occur
  4171. // in this exact order for the copy to work properly:
  4172. arg[0] = arg[3]; arg_map[0] = arg_map[3]; // xpos
  4173. arg[3] = arg[2]; arg_map[3] = arg_map[2]; // height
  4174. arg[2] = width; arg_map[2] = arg_map[1]; // width
  4175. arg[1] = arg[4]; arg_map[1] = arg_map[4]; // ypos
  4176. arg[4] = "A"; arg_map[4] = NULL; // "A" signifies the active window.
  4177. return AddLine(ACT_WINGETPOS, arg, 5, arg_map);
  4178. }
  4179. case OLD_SETENV:
  4180. return AddLine(ACT_ASSIGN, arg, nArgs, arg_map);
  4181. case OLD_ENVADD:
  4182. return AddLine(ACT_ADD, arg, nArgs, arg_map);
  4183. case OLD_ENVSUB:
  4184. return AddLine(ACT_SUB, arg, nArgs, arg_map);
  4185. case OLD_ENVMULT:
  4186. return AddLine(ACT_MULT, arg, nArgs, arg_map);
  4187. case OLD_ENVDIV:
  4188. return AddLine(ACT_DIV, arg, nArgs, arg_map);
  4189. // For these, break rather than return so that further processing can be done:
  4190. case OLD_IFEQUAL:
  4191. aActionType = ACT_IFEQUAL;
  4192. break;
  4193. case OLD_IFNOTEQUAL:
  4194. aActionType = ACT_IFNOTEQUAL;
  4195. break;
  4196. case OLD_IFGREATER:
  4197. aActionType = ACT_IFGREATER;
  4198. break;
  4199. case OLD_IFGREATEROREQUAL:
  4200. aActionType = ACT_IFGREATEROREQUAL;
  4201. break;
  4202. case OLD_IFLESS:
  4203. aActionType = ACT_IFLESS;
  4204. break;
  4205. case OLD_IFLESSOREQUAL:
  4206. aActionType = ACT_IFLESSOREQUAL;
  4207. break;
  4208. #ifdef _DEBUG
  4209. default:
  4210. return ScriptError("DEBUG: Unhandled Old-Command.", action_name);
  4211. #endif
  4212. } // switch()
  4213. }
  4214. //////////////////////////////////////////////////////////////////////////////////////////////////
  4215. // Handle AutoIt2-style IF-statements (i.e. the IF's action is on the same line as the condition).
  4216. //////////////////////////////////////////////////////////////////////////////////////////////////
  4217. // The check below: Don't bother if this IF (e.g. IfWinActive) has zero params or if the
  4218. // subaction was already found above:
  4219. if (nArgs && !subaction_type && !suboldaction_type && ACT_IS_IF_OLD(aActionType, aOldActionType))
  4220. {
  4221. char *delimiter;
  4222. char *last_arg = arg[nArgs - 1];
  4223. for (mark = (int)(last_arg - action_args); action_args[mark]; ++mark)
  4224. {
  4225. if (action_args[mark] == g_delimiter && !literal_map[mark]) // Match found: a non-literal delimiter.
  4226. {
  4227. delimiter = action_args + mark; // save the location of this delimiter
  4228. // Omit the leading whitespace from the next arg:
  4229. for (++mark; IS_SPACE_OR_TAB(action_args[mark]); ++mark);
  4230. // Now <mark> marks the end of the string, the start of the next arg,
  4231. // or a delimiter-char (if the next arg is blank).
  4232. subaction_start = action_args + mark;
  4233. if (subaction_end_marker = ParseActionType(subaction_name, subaction_start, false))
  4234. {
  4235. if ( !(subaction_type = ConvertActionType(subaction_name)) )
  4236. suboldaction_type = ConvertOldActionType(subaction_name);
  4237. if (subaction_type || suboldaction_type) // A valid sub-action (command) was found.
  4238. {
  4239. // Remove this subaction from its parent line; we want it separate:
  4240. *delimiter = '\0';
  4241. rtrim(last_arg);
  4242. }
  4243. // else leave it as-is, i.e. as part of the last param, because the delimiter
  4244. // found above is probably being used as a literal char even though it isn't
  4245. // escaped, e.g. "ifequal, var1, string with embedded, but non-escaped, commas"
  4246. }
  4247. // else, do nothing; reasoning perhaps similar to above comment.
  4248. break;
  4249. }
  4250. }
  4251. }
  4252. // In v1.0.41, the following one-true-brace styles are also supported:
  4253. // Loop { ; Known limitation: Overlaps with file-pattern loop that retrieves single file of name "{".
  4254. // Loop 5 { ; Also overlaps, this time with file-pattern loop that retrieves numeric filename ending in '{'.
  4255. // Loop %Var% { ; Similar, but like the above seems acceptable given extreme rarity of user intending a file pattern.
  4256. if ((aActionType == ACT_LOOP || aActionType == ACT_WHILE)
  4257. && nArgs == 1 && arg[0][0]) // A loop with exactly one, non-blank arg.
  4258. {
  4259. char *arg1 = arg[0]; // For readability and possibly performance.
  4260. // A loop with the above criteria (exactly one arg) can only validly be a normal/counting loop or
  4261. // a file-pattern loop if its parameter's last character is '{'. For the following reasons, any
  4262. // single-parameter loop that ends in '{' is considered to be one-true brace:
  4263. // 1) Extremely rare that a file-pattern loop such as "Loop filename {" would ever be used,
  4264. // and even if it is, the syntax checker will report an unclosed block, making it apparent
  4265. // to the user that a workaround is needed, such as putting the filename into a variable first.
  4266. // 2) Difficulty and code size of distinguishing all possible valid-one-true-braces from those
  4267. // that aren't. For example, the following are ambiguous, so it seems best for consistency
  4268. // and code size reduction just to treat them as one-truce-brace, which will immediately alert
  4269. // the user if the brace isn't closed:
  4270. // a) Loop % (expression) { ; Ambiguous because expression could resolve to a string, thus it would be seen as a file-pattern loop.
  4271. // b) Loop %Var% { ; Similar as above, which means all three of these unintentionally support
  4272. // c) Loop filename{ ; OTB for some types of file loops because it's not worth the code size to "unsupport" them.
  4273. // d) Loop *.txt { ; Like the above: Unintentionally supported, but not documnented.
  4274. // e) (While-loops are also checked here now)
  4275. // Insist that no characters follow the '{' in case the user intended it to be a file-pattern loop
  4276. // such as "Loop {literal-filename".
  4277. char *arg1_last_char = arg1 + strlen(arg1) - 1;
  4278. if (*arg1_last_char == '{')
  4279. {
  4280. add_openbrace_afterward = true;
  4281. *arg1_last_char = '\0'; // Since it will be fully handled here, remove the brace from further consideration.
  4282. if (!rtrim(arg1)) // Trimmed down to nothing, so only a brace was present: remove the arg completely.
  4283. if (aActionType == ACT_LOOP)
  4284. nArgs = 0; // This makes later stages recognize it as an infinite loop rather than a zero-iteration loop.
  4285. else // ACT_WHILE
  4286. return ScriptError(ERR_PARAM1_REQUIRED, aLineText);
  4287. }
  4288. }
  4289. if (!AddLine(aActionType, arg, nArgs, arg_map))
  4290. return FAIL;
  4291. if (add_openbrace_afterward)
  4292. if (!AddLine(ACT_BLOCK_BEGIN))
  4293. return FAIL;
  4294. if (!subaction_type && !suboldaction_type) // There is no subaction in this case.
  4295. return OK;
  4296. // Otherwise, recursively add the subaction, and any subactions it might have, beneath
  4297. // the line just added. The following example:
  4298. // IfWinExist, x, y, IfWinNotExist, a, b, Gosub, Sub1
  4299. // would break down into these lines:
  4300. // IfWinExist, x, y
  4301. // IfWinNotExist, a, b
  4302. // Gosub, Sub1
  4303. return ParseAndAddLine(subaction_start, subaction_type, suboldaction_type, subaction_name, subaction_end_marker
  4304. , literal_map + (subaction_end_marker - action_args) // Pass only the relevant substring of literal_map.
  4305. , strlen(subaction_end_marker));
  4306. }
  4307. inline char *Script::ParseActionType(char *aBufTarget, char *aBufSource, bool aDisplayErrors)
  4308. // inline since it's called so often.
  4309. // aBufTarget should be at least MAX_VAR_NAME_LENGTH + 1 in size.
  4310. // Returns NULL if a failure condition occurs; otherwise, the address of the last
  4311. // character of the action name in aBufSource.
  4312. {
  4313. ////////////////////////////////////////////////////////
  4314. // Find the action name and the start of the param list.
  4315. ////////////////////////////////////////////////////////
  4316. // Allows the delimiter between action-type-name and the first param to be optional by
  4317. // relying on the fact that action-type-names can't contain spaces. Find first char in
  4318. // aLineText that is a space, a delimiter, or a tab. Also search for operator symbols
  4319. // so that assignments and IFs without whitespace are supported, e.g. var1=5,
  4320. // if var2<%var3%. Not static in case g_delimiter is allowed to vary:
  4321. DEFINE_END_FLAGS
  4322. char *end_marker = StrChrAny(aBufSource, end_flags);
  4323. if (end_marker) // Found a delimiter.
  4324. {
  4325. if (*end_marker == '=' && end_marker > aBufSource && end_marker[-1] == '.') // Relies on short-circuit boolean order.
  4326. --end_marker; // v1.0.46.01: Support .=, but not any use of '.' because that is reserved as a struct/member operator.
  4327. if (end_marker > aBufSource) // The delimiter isn't very first char in aBufSource.
  4328. --end_marker;
  4329. // else we allow it to be the first char to support "++i" etc.
  4330. }
  4331. else // No delimiter found, so set end_marker to the location of the last char in string.
  4332. end_marker = aBufSource + strlen(aBufSource) - 1;
  4333. // Now end_marker is the character just prior to the first delimiter or whitespace,
  4334. // or (in the case of ++ and --) the first delimiter itself. Find the end of
  4335. // the action-type name by omitting trailing whitespace:
  4336. end_marker = omit_trailing_whitespace(aBufSource, end_marker);
  4337. // If first char in aBufSource is a delimiter, action_name will consist of just that first char:
  4338. size_t action_name_length = end_marker - aBufSource + 1;
  4339. if (action_name_length > MAX_VAR_NAME_LENGTH)
  4340. {
  4341. if (aDisplayErrors)
  4342. ScriptError(ERR_UNRECOGNIZED_ACTION, aBufSource); // Short/vague message since so rare.
  4343. return NULL;
  4344. }
  4345. strlcpy(aBufTarget, aBufSource, action_name_length + 1);
  4346. return end_marker;
  4347. }
  4348. inline ActionTypeType Script::ConvertActionType(char *aActionTypeString)
  4349. // inline since it's called so often, but don't keep it in the .h due to #include issues.
  4350. {
  4351. // For the loop's index:
  4352. // Use an int rather than ActionTypeType since it's sure to be large enough to go beyond
  4353. // 256 if there happen to be exactly 256 actions in the array:
  4354. for (int action_type = ACT_FIRST_COMMAND; action_type < g_ActionCount; ++action_type)
  4355. if (!stricmp(aActionTypeString, g_act[action_type].Name)) // Match found.
  4356. return action_type;
  4357. return ACT_INVALID; // On failure to find a match.
  4358. }
  4359. inline ActionTypeType Script::ConvertOldActionType(char *aActionTypeString)
  4360. // inline since it's called so often, but don't keep it in the .h due to #include issues.
  4361. {
  4362. for (int action_type = OLD_INVALID + 1; action_type < g_OldActionCount; ++action_type)
  4363. if (!stricmp(aActionTypeString, g_old_act[action_type].Name)) // Match found.
  4364. return action_type;
  4365. return OLD_INVALID; // On failure to find a match.
  4366. }
  4367. bool LegacyArgIsExpression(char *aArgText, char *aArgMap)
  4368. // Helper function for AddLine
  4369. {
  4370. // The section below is here in light of rare legacy cases such as the below:
  4371. // -%y% ; i.e. make it negative.
  4372. // +%y% ; might happen with up/down adjustments on SoundSet, GuiControl progress/slider, etc?
  4373. // Although the above are detected as non-expressions and thus non-double-derefs,
  4374. // the following are not because they're too rare or would sacrifice too much flexibility:
  4375. // 1%y%.0 ; i.e. at a tens/hundreds place and make it a floating point. In addition,
  4376. // 1%y% could be an array, so best not to tag that as non-expression.
  4377. // For that matter, %y%.0 could be an obscure kind of reverse-notation array itself.
  4378. // However, as of v1.0.29, things like %y%000 are allowed, e.g. Sleep %Seconds%000
  4379. // 0x%y% ; i.e. make it hex (too rare to check for, plus it could be an array).
  4380. // %y%%z% ; i.e. concatenate two numbers to make a larger number (too rare to check for)
  4381. char *cp = aArgText + (*aArgText == '-' || *aArgText == '+'); // i.e. +1 if second term evaluates to true.
  4382. return *cp != g_DerefChar // If no deref, for simplicity assume it's an expression since any such non-numeric item would be extremely rare in pre-expression era.
  4383. || !aArgMap || *(aArgMap + (cp != aArgText)) // There's no literal-map or this deref char is not really a deref char because it's marked as a literal.
  4384. || !(cp = strchr(cp + 1, g_DerefChar)) // There is no next deref char.
  4385. || (cp[1] && !IsPureNumeric(cp + 1, false, true, true)); // But that next deref char is not the last char, which means this is not a single isolated deref. v1.0.29: Allow things like Sleep %Var%000.
  4386. // Above does not need to check whether last deref char is marked literal in the
  4387. // arg map because if it is, it would mean the first deref char lacks a matching
  4388. // close-symbol, which will be caught as a syntax error below regardless of whether
  4389. // this is an expression.
  4390. }
  4391. ResultType Script::AddLine(ActionTypeType aActionType, char *aArg[], ArgCountType aArgc, char *aArgMap[])
  4392. // aArg must be a collection of pointers to memory areas that are modifiable, and there
  4393. // must be at least aArgc number of pointers in the aArg array. In v1.0.40, a caller (namely
  4394. // the "macro expansion" for remappings such as "a::b") is allowed to pass a non-NULL value for
  4395. // aArg but a NULL value for aArgMap.
  4396. // Returns OK or FAIL.
  4397. {
  4398. #ifdef _DEBUG
  4399. if (aActionType == ACT_INVALID)
  4400. return ScriptError("DEBUG: BAD AddLine", aArgc > 0 ? aArg[0] : "");
  4401. #endif
  4402. bool do_update_labels;
  4403. if (!aArg && aArgc == UCHAR_MAX) // Special signal from caller to avoid pointing any pending labels to this particular line.
  4404. {
  4405. aArgc = 0;
  4406. do_update_labels = false;
  4407. }
  4408. else
  4409. do_update_labels = true;
  4410. Var *target_var;
  4411. DerefType deref[MAX_DEREFS_PER_ARG]; // Will be used to temporarily store the var-deref locations in each arg.
  4412. int deref_count; // How many items are in deref array.
  4413. ArgStruct *new_arg; // We will allocate some dynamic memory for this, then hang it onto the new line.
  4414. size_t operand_length;
  4415. char *op_begin, *op_end, orig_char;
  4416. char *this_aArgMap, *this_aArg, *cp;
  4417. int open_parens;
  4418. ActionTypeType *np;
  4419. TransformCmds trans_cmd;
  4420. bool is_function;
  4421. //////////////////////////////////////////////////////////
  4422. // Build the new arg list in dynamic memory.
  4423. // The allocated structs will be attached to the new line.
  4424. //////////////////////////////////////////////////////////
  4425. if (!aArgc)
  4426. new_arg = NULL; // Just need an empty array in this case.
  4427. else
  4428. {
  4429. if ( !(new_arg = (ArgStruct *)SimpleHeap::Malloc(aArgc * sizeof(ArgStruct))) )
  4430. return ScriptError(ERR_OUTOFMEM);
  4431. int i, j, i_plus_one;
  4432. bool in_quotes;
  4433. for (i = 0; i < aArgc; ++i)
  4434. {
  4435. ////////////////
  4436. // FOR EACH ARG:
  4437. ////////////////
  4438. this_aArg = aArg[i]; // For performance and convenience.
  4439. this_aArgMap = aArgMap ? aArgMap[i] : NULL; // Same.
  4440. ArgStruct &this_new_arg = new_arg[i]; // Same.
  4441. this_new_arg.is_expression = false; // Set default early, for maintainability.
  4442. if (aActionType == ACT_TRANSFORM)
  4443. {
  4444. if (i == 1) // The second parameter (since the first is the OutputVar).
  4445. // Note that the following might return TRANS_CMD_INVALID just because the sub-command
  4446. // is containined in a variable reference. That is why TRANS_CMD_INVALID does not
  4447. // produce an error at this stage, but only later when the line has been constructed
  4448. // far enough to call ArgHasDeref():
  4449. trans_cmd = Line::ConvertTransformCmd(this_aArg);
  4450. // The value of trans_cmd is also used by the syntax checker further below.
  4451. else if (i > 1) // i.e. Not the first param, only the third and fourth, which currently are either both numeric or both non-numeric for all cases.
  4452. {
  4453. switch(trans_cmd)
  4454. {
  4455. TRANSFORM_NON_EXPRESSION_CASES
  4456. default:
  4457. // For all other sub-commands, Arg #3 and #4 are expression-capable and will be made so
  4458. // if they pass the following check:
  4459. this_new_arg.is_expression = LegacyArgIsExpression(this_aArg, this_aArgMap);
  4460. }
  4461. }
  4462. }
  4463. // Before allocating memory for this Arg's text, first check if it's a pure
  4464. // variable. If it is, we store it differently (and there's no need to resolve
  4465. // escape sequences in these cases, since var names can't contain them):
  4466. if (aActionType == ACT_LOOP && i == 1 && aArg[0] && !stricmp(aArg[0], "Parse")) // Verified.
  4467. // i==1 --> 2nd arg's type is based on 1st arg's text.
  4468. this_new_arg.type = ARG_TYPE_INPUT_VAR;
  4469. else
  4470. this_new_arg.type = Line::ArgIsVar(aActionType, i);
  4471. // Since some vars are optional, the below allows them all to be blank or
  4472. // not present in the arg list. If a mandatory var is blank at this stage,
  4473. // it's okay because all mandatory args are validated to be non-blank elsewhere:
  4474. if (this_new_arg.type != ARG_TYPE_NORMAL)
  4475. {
  4476. if (!*this_aArg)
  4477. // An optional input or output variable has been omitted, so indicate
  4478. // that this arg is not a variable, just a normal empty arg. Functions
  4479. // such as ListLines() rely on this having been done because they assume,
  4480. // for performance reasons, that args marked as variables really are
  4481. // variables. In addition, ExpandArgs() relies on this having been done
  4482. // as does the load-time validation for ACT_DRIVEGET:
  4483. this_new_arg.type = ARG_TYPE_NORMAL;
  4484. else
  4485. {
  4486. // Does this input or output variable contain a dereference? If so, it must
  4487. // be resolved at runtime (to support arrays, etc.).
  4488. // Find the first non-escaped dereference symbol:
  4489. for (j = 0; this_aArg[j] && (this_aArg[j] != g_DerefChar || (this_aArgMap && this_aArgMap[j])); ++j);
  4490. if (!this_aArg[j])
  4491. {
  4492. // A non-escaped deref symbol wasn't found, therefore this variable does not
  4493. // appear to be something that must be resolved dynamically at runtime.
  4494. if ( !(target_var = FindOrAddVar(this_aArg)) )
  4495. return FAIL; // The above already displayed the error.
  4496. // If this action type is something that modifies the contents of the var, ensure the var
  4497. // isn't a special/reserved one:
  4498. if (this_new_arg.type == ARG_TYPE_OUTPUT_VAR && VAR_IS_READONLY(*target_var))
  4499. return ScriptError(ERR_VAR_IS_READONLY, this_aArg);
  4500. // Rather than removing this arg from the list altogether -- which would distrub
  4501. // the ordering and hurt the maintainability of the code -- the next best thing
  4502. // in terms of saving memory is to store an empty string in place of the arg's
  4503. // text if that arg is a pure variable (i.e. since the name of the variable is already
  4504. // stored in the Var object, we don't need to store it twice):
  4505. this_new_arg.text = "";
  4506. this_new_arg.length = 0;
  4507. this_new_arg.deref = (DerefType *)target_var;
  4508. continue;
  4509. }
  4510. // else continue on to the below so that this input or output variable name's dynamic part
  4511. // (e.g. array%i%) can be partially resolved.
  4512. }
  4513. }
  4514. else // this_new_arg.type == ARG_TYPE_NORMAL (excluding those input/output_vars that were converted to normal because they were blank, above).
  4515. {
  4516. // v1.0.29: Allow expressions in any parameter that starts with % followed by a space
  4517. // or tab. This should be unambiguous because spaces and tabs are illegal in variable names.
  4518. // Since there's little if any benefit to allowing input and output variables to be
  4519. // dynamically built via expression, for now it is disallowed. If ever allow it,
  4520. // need to review other sections to ensure they will tolerate it. Also, the following
  4521. // would probably need revision to get it to be detected as an output-variable:
  4522. // % Array%i% = value
  4523. if (*this_aArg == g_DerefChar && !(this_aArgMap && *this_aArgMap) // It's a non-literal deref character.
  4524. && IS_SPACE_OR_TAB(this_aArg[1])) // Followed by a space or tab.
  4525. {
  4526. this_new_arg.is_expression = true;
  4527. // Omit the percent sign and the space after it from further consideration.
  4528. this_aArg += 2;
  4529. if (this_aArgMap)
  4530. this_aArgMap += 2;
  4531. // ACT_ASSIGN isn't capable of dealing with expressions because ExecUntil() does not
  4532. // call ExpandArgs() automatically for it. Thus its function, PerformAssign(), would
  4533. // not be given the expanded result of the expression.
  4534. if (aActionType == ACT_ASSIGN)
  4535. aActionType = ACT_ASSIGNEXPR;
  4536. }
  4537. }
  4538. // Below will set the new var to be the constant empty string if the
  4539. // source var is NULL or blank.
  4540. // e.g. If WinTitle is unspecified (blank), but WinText is non-blank.
  4541. // Using empty string is much safer than NULL because these args
  4542. // will be frequently accessed by various functions that might
  4543. // not be equipped to handle NULLs. Rather than having to remember
  4544. // to check for NULL in every such case, setting it to a constant
  4545. // empty string here should make things a lot more maintainable
  4546. // and less bug-prone. If there's ever a need for the contents
  4547. // of this_new_arg to be modifiable (perhaps some obscure API calls require
  4548. // modifiable strings?) can malloc a single-char to contain the empty string.
  4549. //
  4550. // So that it can be passed to Malloc(), first update the length to match what the text will be
  4551. // (if the alloc fails, an inaccurate length won't matter because it's an program-abort situation).
  4552. // The length must fit into a WORD, which it will since each arg is literal text from a script's line,
  4553. // which is limited to LINE_SIZE. The length member was added in v1.0.44.14 to boost runtime performance.
  4554. this_new_arg.length = (WORD)strlen(this_aArg);
  4555. if ( !(this_new_arg.text = SimpleHeap::Malloc(this_aArg, this_new_arg.length)) )
  4556. return FAIL; // It already displayed the error for us.
  4557. ////////////////////////////////////////////////////
  4558. // Build the list of dereferenced vars for this arg.
  4559. ////////////////////////////////////////////////////
  4560. // Now that any escaped g_DerefChars have been marked, scan new_arg.text to
  4561. // determine where the variable dereferences are (if any). In addition to helping
  4562. // runtime performance, this also serves to validate the script at load-time
  4563. // so that some errors can be caught early. Note: this_new_arg.text is scanned rather
  4564. // than this_aArg because we want to establish pointers to the correct area of
  4565. // memory:
  4566. deref_count = 0; // Init for each arg.
  4567. if (np = g_act[aActionType].NumericParams) // This command has at least one numeric parameter.
  4568. {
  4569. // As of v1.0.25, pure numeric parameters can optionally be numeric expressions, so check for that:
  4570. i_plus_one = i + 1;
  4571. for (; *np; ++np)
  4572. {
  4573. if (*np == i_plus_one) // This arg is enforced to be purely numeric.
  4574. {
  4575. if (aActionType == ACT_WINMOVE)
  4576. {
  4577. if (i > 1)
  4578. {
  4579. // i indicates this is Arg #3 or beyond, which is one of the args that is
  4580. // either the word "default" or a number/expression.
  4581. if (!stricmp(this_new_arg.text, "default")) // It's not an expression.
  4582. break; // The loop is over because this arg was found in the list.
  4583. }
  4584. else // This is the first or second arg, which are title/text vs. X/Y when aArgc > 2.
  4585. if (aArgc > 2) // Title/text are not numeric/expressions.
  4586. break; // The loop is over because this arg was found in the list.
  4587. }
  4588. // Otherwise, it might be an expression so do the final checks.
  4589. // Override the original false default of is_expression unless an exception applies.
  4590. // Since ACT_ASSIGNEXPR and ACT_WHILE aren't legacy commands, don't call
  4591. // LegacyArgIsExpression() for them because that would cause things like x:=%y% and
  4592. // "while %x%" to behave the same as x:=y and "while x:, which would be inconsistent
  4593. // with how expressions are supposed to work. ACT_RETURN should have been excluded
  4594. // too; but it was left out for so long that it was thought best to document and keep
  4595. // the unexpected behavior of "return %x%".
  4596. // For other commands, if any telltale character is present it's definitely an
  4597. // expression because this is an arg that's marked as a number-or-expression.
  4598. // So telltales avoid the need for the complex check further below.
  4599. if (aActionType == ACT_ASSIGNEXPR || aActionType == ACT_WHILE // See above.
  4600. || StrChrAny(this_new_arg.text, EXPR_TELLTALES)) // See above.
  4601. this_new_arg.is_expression = true;
  4602. else
  4603. this_new_arg.is_expression = LegacyArgIsExpression(this_new_arg.text, this_aArgMap);
  4604. break; // The loop is over if this arg is found in the list of mandatory-numeric args.
  4605. } // i is a mandatory-numeric arg
  4606. } // for each mandatory-numeric arg of this command, see if this arg matches its number.
  4607. } // this command has a list of mandatory numeric-args.
  4608. // To help runtime performance, the below changes an ACT_ASSIGNEXPR, ACT_TRANSFORM, and
  4609. // perhaps others in the future, to become non-expressions if they contain only a single
  4610. // numeric literal (or are entirely blank). At runtime, such args are expanded normally
  4611. // rather than having to run them through the expression evaluator:
  4612. if (this_new_arg.is_expression && IsPureNumeric(this_new_arg.text, true, true, true))
  4613. this_new_arg.is_expression = false;
  4614. if (this_new_arg.is_expression)
  4615. {
  4616. // Ensure parentheses are balanced:
  4617. for (cp = this_new_arg.text, in_quotes = false, open_parens = 0; *cp; ++cp)
  4618. {
  4619. switch (*cp)
  4620. {
  4621. // The simple method below is sufficient for our purpose even if a quoted string contains
  4622. // pairs of double-quotes to represent a single literal quote, e.g. "quoted ""word""".
  4623. // In other words, it relies on the fact that there must be an even number of quotes
  4624. // inside any mandatory-numeric arg that is an expression such as x=="red,blue"
  4625. case '"':
  4626. in_quotes = !in_quotes;
  4627. break;
  4628. case '(':
  4629. if (!in_quotes) // Literal parentheses inside a quoted string should not be counted for this purpose.
  4630. ++open_parens;
  4631. break;
  4632. case ')':
  4633. if (!in_quotes)
  4634. {
  4635. if (!open_parens)
  4636. return ScriptError(ERR_MISSING_OPEN_PAREN, cp); // And indicate cp as the exact spot.
  4637. --open_parens;
  4638. }
  4639. break;
  4640. }
  4641. }
  4642. if (open_parens) // At least one '(' is never closed.
  4643. return ScriptError(ERR_MISSING_CLOSE_PAREN, this_new_arg.text);
  4644. #define ERR_EXP_ILLEGAL_CHAR "The leftmost character above is illegal in an expression." // "above" refers to the layout of the error dialog.
  4645. // ParseDerefs() won't consider escaped percent signs to be illegal, but in this case
  4646. // they should be since they have no meaning in expressions. UPDATE for v1.0.44.11: The following
  4647. // is now commented out because it causes false positives (and fixing that probably isn't worth the
  4648. // performance & code size). Specifically, the section below reports an error for escaped delimiters
  4649. // inside quotes such as x := "`%". More importantly, it defeats the continuation section's %
  4650. // option; for example:
  4651. // MsgBox %
  4652. // (% ; <<< This option here is defeated because it causes % to be replaced with `% at an early stage.
  4653. // "%"
  4654. // )
  4655. //if (this_aArgMap) // This arg has an arg map indicating which chars are escaped/literal vs. normal.
  4656. // for (j = 0; this_new_arg.text[j]; ++j)
  4657. // if (this_aArgMap[j] && this_new_arg.text[j] == g_DerefChar)
  4658. // return ScriptError(ERR_EXP_ILLEGAL_CHAR, this_new_arg.text + j);
  4659. // Resolve all operands (that aren't numbers) into variable references. Doing this here at
  4660. // load-time greatly improves runtime performance, especially for scripts that have a lot
  4661. // of variables.
  4662. for (op_begin = this_new_arg.text; *op_begin; op_begin = op_end)
  4663. {
  4664. if (*op_begin == '.' && op_begin[1] == '=') // v1.0.46.01: Support .=, but not any use of '.' because that is reserved as a struct/member operator.
  4665. op_begin += 2;
  4666. for (; *op_begin && strchr(EXPR_OPERAND_TERMINATORS, *op_begin); ++op_begin); // Skip over whitespace, operators, and parentheses.
  4667. if (!*op_begin) // The above loop reached the end of the string: No operands remaining.
  4668. break;
  4669. // Now op_begin is the start of an operand, which might be a variable reference, a numeric
  4670. // literal, or a string literal. If it's a string literal, it is left as-is:
  4671. if (*op_begin == '"')
  4672. {
  4673. // Find the end of this string literal, noting that a pair of double quotes is
  4674. // a literal double quote inside the string:
  4675. for (op_end = op_begin + 1;; ++op_end)
  4676. {
  4677. if (!*op_end)
  4678. return ScriptError(ERR_MISSING_CLOSE_QUOTE, op_begin);
  4679. if (*op_end == '"') // If not followed immediately by another, this is the end of it.
  4680. {
  4681. ++op_end;
  4682. if (*op_end != '"') // String terminator or some non-quote character.
  4683. break; // The previous char is the ending quote.
  4684. //else a pair of quotes, which resolves to a single literal quote.
  4685. // This pair is skipped over and the loop continues until the real end-quote is found.
  4686. }
  4687. }
  4688. // op_end is now set correctly to allow the outer loop to continue.
  4689. continue; // Ignore this literal string, letting the runtime expression parser recognize it.
  4690. }
  4691. // Find the end of this operand (if *op_end is '\0', strchr() will find that too):
  4692. for (op_end = op_begin + 1; !strchr(EXPR_OPERAND_TERMINATORS, *op_end); ++op_end); // Find first whitespace, operator, or paren.
  4693. if (*op_end == '=' && op_end[-1] == '.') // v1.0.46.01: Support .=, but not any use of '.' because that is reserved as a struct/member operator.
  4694. --op_end;
  4695. // Now op_end marks the end of this operand. The end might be the zero terminator, an operator, etc.
  4696. // Must be done only after op_end has been set above (since loop uses op_end):
  4697. if (*op_begin == '.' && strchr(" \t=", op_begin[1])) // If true, it can't be something like "5." because the dot inside would never be parsed separately in that case. Also allows ".=" operator.
  4698. continue;
  4699. //else any '.' not followed by a space, tab, or '=' is likely a number without a leading zero,
  4700. // so continue on below to process it.
  4701. operand_length = op_end - op_begin;
  4702. // Check if it's AND/OR/NOT:
  4703. if (operand_length < 4 && operand_length > 1) // Ordered for short-circuit performance.
  4704. {
  4705. if (operand_length == 2)
  4706. {
  4707. if ((*op_begin == 'o' || *op_begin == 'O') && (op_begin[1] == 'r' || op_begin[1] == 'R'))
  4708. { // "OR" was found.
  4709. op_begin[0] = '|'; // v1.0.45: Transform into easier-to-parse symbols for improved
  4710. op_begin[1] = '|'; // runtime performance and reduced code size. v1.0.48: It no longer helps runtime performance, but it's kept because changing moving it to ExpressionToPostfix() isn't likely to have much benefit.
  4711. continue;
  4712. }
  4713. }
  4714. else // operand_length must be 3
  4715. {
  4716. switch (*op_begin)
  4717. {
  4718. case 'a':
  4719. case 'A':
  4720. if ( (op_begin[1] == 'n' || op_begin[1] == 'N') // Relies on short-circuit boolean order.
  4721. && (op_begin[2] == 'd' || op_begin[2] == 'D') )
  4722. { // "AND" was found.
  4723. op_begin[0] = '&'; // v1.0.45: Transform into easier-to-parse symbols for
  4724. op_begin[1] = '&'; // improved runtime performance and reduced code size. v1.0.48: It no longer helps runtime performance, but it's kept because changing moving it to ExpressionToPostfix() isn't likely to have much benefit.
  4725. op_begin[2] = ' '; // A space is used lieu of the complexity of the below.
  4726. // Above seems better than below even though below would make it look a little
  4727. // nicer in ListLines. BELOW CAN'T WORK because this_new_arg.deref[] can contain
  4728. // offsets that would also need to be adjusted:
  4729. //memmove(op_begin + 2, op_begin + 3, strlen(op_begin+3)+1 ... or some expression involving this_new_arg.length this_new_arg.text);
  4730. //--this_new_arg.length;
  4731. //--op_end; // Ensure op_end is set up properly for the for-loop's post-iteration action.
  4732. continue;
  4733. }
  4734. break;
  4735. case 'n': // v1.0.45: Unlike "AND" and "OR" above, this one is not given a substitute
  4736. case 'N': // because it's not the same as the "!" operator. See SYM_LOWNOT for comments.
  4737. if ( (op_begin[1] == 'o' || op_begin[1] == 'O') // Relies on short-circuit boolean order.
  4738. && (op_begin[2] == 't' || op_begin[2] == 'T') )
  4739. continue; // "NOT" was found.
  4740. break;
  4741. }
  4742. }
  4743. } // End of check for AND/OR/NOT.
  4744. // Temporarily terminate, which avoids at least the below issue:
  4745. // Two or more extremely long var names together could exceed MAX_VAR_NAME_LENGTH
  4746. // e.g. LongVar%LongVar2% would be too long to store in a buffer of size MAX_VAR_NAME_LENGTH.
  4747. // This seems pretty darn unlikely, but perhaps doubling it would be okay.
  4748. // UPDATE: Above is now not an issue since caller's string is temporarily terminated rather
  4749. // than making a copy of it.
  4750. orig_char = *op_end;
  4751. *op_end = '\0';
  4752. // Illegal characters are legal when enclosed in double quotes. So the following is
  4753. // done only after the above has ensured this operand is not one enclosed entirely in
  4754. // double quotes.
  4755. // The following characters are either illegal in expressions or reserved for future use.
  4756. // Rather than forbidding g_delimiter and g_DerefChar, it seems best to assume they are at
  4757. // their default values for this purpose. Otherwise, if g_delimiter is an operator, that
  4758. // operator would then become impossible inside the expression.
  4759. if (cp = StrChrAny(op_begin, EXPR_ILLEGAL_CHARS))
  4760. return ScriptError(ERR_EXP_ILLEGAL_CHAR, cp);
  4761. // Below takes care of recognizing hexadecimal integers, which avoids the 'x' character
  4762. // inside of something like 0xFF from being detected as the name of a variable:
  4763. if ( !IsPureNumeric(op_begin, true, false, true) // Not a numeric literal...
  4764. && !(*op_begin == '?' && !op_begin[1]) ) // ...and not an isolated '?' operator. Relies on short-circuit boolean order.
  4765. {
  4766. is_function = (orig_char == '(');
  4767. // This operand must be a variable/function reference or string literal, otherwise it's
  4768. // a syntax error.
  4769. // Check explicitly for derefs since the vast majority don't have any, and this
  4770. // avoids the function call in those cases:
  4771. if (strchr(op_begin, g_DerefChar)) // This operand contains at least one double dereference.
  4772. {
  4773. // v1.0.47.06: Dynamic function calls are now supported.
  4774. //if (is_function)
  4775. // return ScriptError("Dynamic function calls are not supported.", op_begin);
  4776. int first_deref = deref_count;
  4777. // The percent-sign derefs are parsed and added to the deref array at this stage (on a
  4778. // per-operand basis) rather than all at once for the entire arg because
  4779. // the deref array must contain both percent-sign derefs and non-%-derefs interspersed
  4780. // and ordered according to their physical position inside the arg, but ParseDerefs
  4781. // only handles percent-sign derefs, not expresion derefs like x+y. In the following
  4782. // example, the order of derefs must be x,i,y: if (x = Array%i% and y = 3)
  4783. if (!ParseDerefs(op_begin, this_aArgMap ? this_aArgMap + (op_begin - this_new_arg.text) : NULL
  4784. , deref, deref_count))
  4785. return FAIL; // It already displayed the error. No need to undo temp. termination.
  4786. // And now leave this operand "raw" so that it will later be dereferenced again.
  4787. // In the following example, i made into a deref but the result (Array33) must be
  4788. // dereferenced during a second stage at runtime: if (x = Array%i%).
  4789. if (is_function) // Dynamic function call.
  4790. {
  4791. int param_count = 0;
  4792. // Determine how many parameters there are.
  4793. cp = omit_leading_whitespace(op_end + 1);
  4794. if (*cp != ')')
  4795. {
  4796. int open_parens;
  4797. bool in_quote = false;
  4798. for (++param_count, open_parens = 1; *cp && open_parens; ++cp)
  4799. {
  4800. if (*cp == '"')
  4801. in_quote = !in_quote;
  4802. if (in_quote)
  4803. continue;
  4804. switch (*cp)
  4805. {
  4806. case '(':
  4807. ++open_parens;
  4808. break;
  4809. case ')':
  4810. --open_parens;
  4811. break;
  4812. case ',':
  4813. if (open_parens == 1)
  4814. ++param_count;
  4815. break;
  4816. }
  4817. }
  4818. }
  4819. // Store param_count in the first deref. This will be picked up by the expression
  4820. // infix processing code.
  4821. deref[first_deref].param_count = param_count; // This is done only for dynamic function calls because non-dynamic ones have their param_count set by PreparseBlocks().
  4822. }
  4823. }
  4824. else // This operand is a variable name or function name (single deref).
  4825. {
  4826. #define TOO_MANY_REFS "Too many var/func refs." // Short msg since so rare.
  4827. if (deref_count >= MAX_DEREFS_PER_ARG)
  4828. return ScriptError(TOO_MANY_REFS, op_begin); // Indicate which operand it ran out of space at.
  4829. // Store the deref's starting location, even for functions (leave it set to the start
  4830. // of the function's name for use when doing error reporting at other stages -- i.e.
  4831. // don't set it to the address of the first param or closing-paren-if-no-params):
  4832. deref[deref_count].marker = op_begin;
  4833. deref[deref_count].length = (DerefLengthType)operand_length;
  4834. if (deref[deref_count].is_function = is_function) // It's a function not a variable.
  4835. // Set to NULL to catch bugs. It must and will be filled in at a later stage
  4836. // because the setting of each function's mJumpToLine relies upon the fact that
  4837. // functions are added to the linked list only upon being formally defined
  4838. // so that the most recently defined function is always last in the linked
  4839. // list, awaiting its mJumpToLine that will appear beneath it.
  4840. deref[deref_count].func = NULL;
  4841. else // It's a variable (or a scientific-notation literal) rather than a function.
  4842. {
  4843. if (toupper(op_end[-1]) == 'E' && (orig_char == '+' || orig_char == '-') // Listed first for short-circuit performance with the below.
  4844. && strchr(op_begin, '.')) // v1.0.46.11: This item appears to be a scientific-notation literal with the OPTIONAL +/- sign PRESENT on the exponent (e.g. 1.0e+001), so check that before checking if it's a variable name.
  4845. {
  4846. *op_end = orig_char; // Undo the temporary termination.
  4847. do // Skip over the sign and its exponent; e.g. the "+1" in "1.0e+1". There must be a sign in this particular sci-notation number or we would never have arrived here.
  4848. ++op_end;
  4849. while (*op_end >= '0' && *op_end <= '9'); // Avoid isdigit() because it sometimes causes a debug assertion failure at: (unsigned)(c + 1) <= 256 (probably only in debug mode), and maybe only when bad data got in it due to some other bug.
  4850. // No need to do the following because a number can't validly be followed by the ".=" operator:
  4851. //if (*op_end == '=' && op_end[-1] == '.') // v1.0.46.01: Support .=, but not any use of '.' because that is reserved as a struct/member operator.
  4852. // --op_end;
  4853. continue; // Pure number, which doesn't need any processing at this stage.
  4854. }
  4855. // Since above didn't "continue", treat this item as a variable name:
  4856. if ( !(deref[deref_count].var = FindOrAddVar(op_begin, operand_length)) )
  4857. return FAIL; // The called function already displayed the error.
  4858. }
  4859. ++deref_count; // Since above didn't "continue" or "return".
  4860. }
  4861. }
  4862. //else purely numeric or '?'. Do nothing since pure numbers and '?' don't need any
  4863. // processing at this stage.
  4864. *op_end = orig_char; // Undo the temporary termination.
  4865. } // expression pre-parsing loop.
  4866. // Now that the derefs have all been recognized above, simplify any special cases --
  4867. // such as single isolated derefs -- to enhance runtime performance.
  4868. //
  4869. // There used to be a section here that translated each expression that consisted
  4870. // solely of a quoted/literal string into a non-expression (except Post/SendMessage).
  4871. // However, that is no longer appropriate for ACT_ASSIGNEXPR (which was the main
  4872. // beneficiary) because an optimization further below would wrongly apply
  4873. // SetFormat to the assigning of a quoted/literal string like Var:="55".
  4874. // Benchmarks show that performance of assigning quoted literal strings is only
  4875. // slightly slower when is_expression==true; also, the savings in code size and the
  4876. // fact that the translation made ListLines inaccurate (due to the omitted quotes)
  4877. // seem to support getting rid of that section.
  4878. //
  4879. // Make things like "Sleep Var" and "Var := X" into non-expressions. At runtime,
  4880. // such args are expanded normally rather than having to run them through the
  4881. // expression evaluator. A simple test script shows that this one change can
  4882. // double the runtime performance of certain commands such as EnvAdd:
  4883. // Below is somewhat obsolete but kept for reference:
  4884. // This policy is basically saying that expressions are allowed to evaluate to strings
  4885. // everywhere appropriate, but that at the moment the only appropriate place is x := y
  4886. // because all other expressions should resolve to a numeric value by virtue of the fact
  4887. // that they *are* numeric parameters. ValidateName() serves to eliminate cases where
  4888. // a single deref is accompanied by literal numbers, strings, or operators, e.g.
  4889. // Var := X + 1 ... Var := Var2 "xyz" ... Var := -Var2
  4890. if (deref_count == 1 && Var::ValidateName(this_new_arg.text, false, DISPLAY_NO_ERROR)) // Single isolated deref.
  4891. {
  4892. // ACT_WHILE performs less than 4% faster as a non-expression in these cases, and keeping
  4893. // it as an expression avoids an extra check in a performance-sensitive spot of ExpandArgs
  4894. // (near mActionType <= ACT_LAST_OPTIMIZED_IF).
  4895. if (aActionType != ACT_WHILE) // If it is ACT_WHILE, it would be something like "while x" in this case. Keep those as expressions for the reason above.
  4896. this_new_arg.is_expression = false; // In addition to being an optimization, doing this might also be necessary for things like "Var := ClipboardAll" to work properly.
  4897. // But if aActionType is ACT_ASSIGNEXPR, it's left as ACT_ASSIGNEXPR vs. ACT_ASSIGN
  4898. // because it might be necessary to avoid having AutoTrim take effect for := (which
  4899. // it never should). In addition, ACT_ASSIGNEXPR probably performs better than
  4900. // ACT_ASSIGN when is_expression==false.
  4901. }
  4902. else if (deref_count && !StrChrAny(this_new_arg.text, EXPR_OPERAND_TERMINATORS)) // No spaces, tabs, etc.
  4903. {
  4904. // Adjust if any of the following special cases apply:
  4905. // x := y -> Mark as non-expression (after expression-parsing set up parsed derefs above)
  4906. // so that the y deref will be only a single-deref to be directly stored in x.
  4907. // This is done in case y contains a string. Since an expression normally
  4908. // evaluates to a number, without this workaround, x := y would be useless for
  4909. // a simple assignment of a string. This case is handled above.
  4910. // x := %y% -> Mark the right-side arg as an input variable so that it will be doubly
  4911. // dereferenced, similar to StringTrimRight, Out, %y%, 0. This seems best
  4912. // because there would be little or no point to having it behave identically
  4913. // to x := y. It might even be confusing in light of the next case below.
  4914. // CASE #3:
  4915. // x := Literal%y%Literal%z%Literal -> Same as above. This is done mostly to support
  4916. // retrieving array elements whose contents are *non-numeric* without having to use
  4917. // something like StringTrimRight.
  4918. // Now we know it has at least one deref. But if any operators or other characters disallowed
  4919. // in variables are present, it all three cases are disqualified and kept as expressions.
  4920. // This check is necessary for all three cases:
  4921. // No operators of any kind anywhere. Not even +/- prefix, since those imply a numeric
  4922. // expression. No chars illegal in var names except the percent signs themselves,
  4923. // e.g. *no* whitespace.
  4924. // Also, the first deref (indeed, all of them) should point to a percent sign, since
  4925. // there should not be any way for non-percent derefs to get mixed in with cases
  4926. // 2 or 3.
  4927. if (!deref[0].is_function && *deref[0].marker == g_DerefChar // This appears to be case #2 or #3.
  4928. && aActionType != ACT_WHILE) // Nearly doubles the speed of "while %x%" and "while Array%i%" to leave WHILE as an expression. But y:=%x% and y:=Array%i% are about the same speed either way, and "if %x%" never reaches this point because for compatibility(?), it's the same as "if x".
  4929. {
  4930. // The comment below is probably obsolete -- and perhaps so is this entire optimization
  4931. // because expressions are faster now. But in case it's necessary for anything related
  4932. // to backward compatibility, it's kept (it may also reduce memory utilization a little
  4933. // because it avoids making simple things into expressions, which require extra memory).
  4934. // OLD: Set it up so that x:=Array%i% behaves the same as StringTrimRight, Out, Array%i%, 0.
  4935. this_new_arg.is_expression = false;
  4936. this_new_arg.type = ARG_TYPE_INPUT_VAR;
  4937. }
  4938. }
  4939. } // if (this_new_arg.is_expression)
  4940. else // this arg does not contain an expression.
  4941. if (!ParseDerefs(this_new_arg.text, this_aArgMap, deref, deref_count))
  4942. return FAIL; // It already displayed the error.
  4943. //////////////////////////////////////////////////////////////
  4944. // Allocate mem for this arg's list of dereferenced variables.
  4945. //////////////////////////////////////////////////////////////
  4946. if (deref_count)
  4947. {
  4948. // +1 for the "NULL-item" terminator:
  4949. if ( !(this_new_arg.deref = (DerefType *)SimpleHeap::Malloc((deref_count + 1) * sizeof(DerefType))) )
  4950. return ScriptError(ERR_OUTOFMEM);
  4951. memcpy(this_new_arg.deref, deref, deref_count * sizeof(DerefType));
  4952. // Terminate the list of derefs with a deref that has a NULL marker:
  4953. this_new_arg.deref[deref_count].marker = NULL;
  4954. }
  4955. else
  4956. this_new_arg.deref = NULL;
  4957. } // for each arg.
  4958. } // there are more than zero args.
  4959. //////////////////////////////////////////////////////////////////////////////////////
  4960. // Now the above has allocated some dynamic memory, the pointers to which we turn over
  4961. // to Line's constructor so that they can be anchored to the new line.
  4962. //////////////////////////////////////////////////////////////////////////////////////
  4963. Line *the_new_line = new Line(mCurrFileIndex, mCombinedLineNumber, aActionType, new_arg, aArgc);
  4964. if (!the_new_line)
  4965. return ScriptError(ERR_OUTOFMEM);
  4966. Line &line = *the_new_line; // For performance and convenience.
  4967. line.mPrevLine = mLastLine; // Whether NULL or not.
  4968. if (mFirstLine == NULL)
  4969. mFirstLine = the_new_line;
  4970. else
  4971. mLastLine->mNextLine = the_new_line;
  4972. // This must be done after the above:
  4973. mLastLine = the_new_line;
  4974. mCurrLine = the_new_line; // To help error reporting.
  4975. ///////////////////////////////////////////////////////////////////
  4976. // Do any post-add validation & handling for specific action types.
  4977. ///////////////////////////////////////////////////////////////////
  4978. #ifndef AUTOHOTKEYSC // For v1.0.35.01, some syntax checking is removed in compiled scripts to reduce their size.
  4979. int value; // For temp use during validation.
  4980. double value_float;
  4981. SYSTEMTIME st; // same.
  4982. #endif
  4983. // v1.0.38: The following should help reduce code size, and for some commands helps load-time
  4984. // performance by avoiding multiple resolutions of a given macro:
  4985. char *new_raw_arg1 = NEW_RAW_ARG1;
  4986. char *new_raw_arg2 = NEW_RAW_ARG2;
  4987. char *new_raw_arg3 = NEW_RAW_ARG3;
  4988. char *new_raw_arg4 = NEW_RAW_ARG4;
  4989. switch(aActionType)
  4990. {
  4991. // Fix for v1.0.35.02:
  4992. // THESE FIRST FEW CASES MUST EXIST IN BOTH SELF-CONTAINED AND NORMAL VERSION since they alter the
  4993. // attributes/members of some types of lines:
  4994. case ACT_SUB:
  4995. if (aArgc < 2) // Validate at loadtime so that at runtime, DETERMINE_NUMERIC_TYPES and ARG2_AS_INT64 don't have to check that mArgc > 1.
  4996. return ScriptError(ERR_PARAM2_REQUIRED);
  4997. // ** DON'T BREAK; FALL INTO NEXT SECTION **
  4998. case ACT_ADD: // ************ OR IT FELL INTO THIS SECTION FROM ABOVE ************
  4999. case ACT_MULT:
  5000. case ACT_DIV:
  5001. #ifndef AUTOHOTKEYSC // For v1.0.35.01, some syntax checking is removed in compiled scripts to reduce their size.
  5002. if (aArgc > 2) // Then this is ACT_ADD OR ACT_SUB with a 3rd parameter (TimeUnits)
  5003. {
  5004. if (*new_raw_arg3 && !line.ArgHasDeref(3))
  5005. if (!strchr("SMHD", toupper(*new_raw_arg3))) // (S)econds, (M)inutes, (H)ours, or (D)ays
  5006. return ScriptError(ERR_PARAM3_INVALID, new_raw_arg3);
  5007. if (aActionType == ACT_SUB && *new_raw_arg2 && !line.ArgHasDeref(2))
  5008. if (!YYYYMMDDToSystemTime(new_raw_arg2, st, true))
  5009. return ScriptError(ERR_INVALID_DATETIME, new_raw_arg2);
  5010. new_arg[1].postfix = NULL; // It's necessary to indicate that there is no cached binary number for arg #2 in the 3-arg mode of ACT_ADD due to runtime logic that checks it. For the others, this helps maintainability.
  5011. break; // Don't allow processing to continue. Other sections below rely on this.
  5012. }
  5013. if (aActionType == ACT_DIV && !line.ArgHasDeref(2) && !new_arg[1].is_expression) // i.e. don't validate the following until runtime:
  5014. if (!ATOF(new_raw_arg2)) // x/=y ... x/=(4/4)/4 (v1.0.46.01: added is_expression check for expressions with no variables or function-calls).
  5015. return ScriptError(ERR_DIVIDEBYZERO, new_raw_arg2);
  5016. // ** DON'T BREAK; FALL INTO NEXT SECTION **
  5017. #endif
  5018. case ACT_ASSIGN: // **** OR IT FELL INTO THIS SECTION FROM ABOVE ****
  5019. case ACT_ASSIGNEXPR:
  5020. case ACT_IFEQUAL:
  5021. case ACT_IFNOTEQUAL:
  5022. case ACT_IFGREATER:
  5023. case ACT_IFGREATEROREQUAL:
  5024. case ACT_IFLESS:
  5025. case ACT_IFLESSOREQUAL:
  5026. case ACT_IFBETWEEN:
  5027. case ACT_IFNOTBETWEEN:
  5028. int arg_index;
  5029. for (arg_index = 1; arg_index < aArgc; ++arg_index) // Up to two iterations: arg #2 and arg#3 (for If[Not]Between)).
  5030. {
  5031. if ( *new_arg[arg_index].text && !line.ArgHasDeref(arg_index+1)
  5032. && !new_arg[arg_index].is_expression // Expressions don't make sense for this, plus they need their postfix member for other purposes.
  5033. && IsPureNumeric(new_arg[arg_index].text, true, false, false) // aAllowImpure==false even for ACT_ADD/SUB/MULT/DIV because those would see almost all impure *LITERAL* numbers like 123abc as variables (too rare anyway). Check for purity to rule out floats and expressions consisting only of literals such as 1+2 (in case they can ever be encountered here).
  5034. && !((aActionType == ACT_ASSIGN || aActionType == ACT_ASSIGNEXPR) // Only these need extra checking because the display format of the number doesn't matter for ADD/SUB/IFEQUAL/IFGREATER/etc. because they treat anything that looks like a number (any format) as a pure number.
  5035. && (
  5036. *new_raw_arg2 == '0' || *new_raw_arg2 == '+' // Assign hex or any unusually-formatted integers the old way so that the format is retained in case its important to the operation of the script (e.g. x:="005", x:=005, x:="0x5", x:="+5", x:=+5).
  5037. || new_arg[1].length > 18 // See below.
  5038. // Integers that are too long are probably intended to be a series of characters/digits,
  5039. // so assign them the old way to keep all of the digits. Fix for v1.0.48.01: Reduced the
  5040. // limit from MAX_INTEGER_LENGTH (20) to 18 so that the assignment (:= and =) of integers
  5041. // that are 19 or 20 digits long work as they did prior to v1.0.48 (some of such integers
  5042. // would overflow a signed 64-bit value, so keep all of them as strings).
  5043. //
  5044. // The following can't happen anymore because x:="string" is no longer translated
  5045. // into is_expression==false. There are some reasons given in a section higher above:
  5046. //|| IS_SPACE_OR_TAB(new_raw_arg2[new_arg[1].length-1]) // Trailing whitespace, which can happen from something like x:="abc ".
  5047. //|| IS_SPACE_OR_TAB(*new_raw_arg2) // This can happen via translation of x:=" abc " to x:= abc at an earlier stage.
  5048. // Any LITERAL whitespace around a LITERAL number has always been ignored/omitted,
  5049. // so storing binary integers for things like "x = 1" and "x := 1" should behave
  5050. // as before, with the exception of "SetFormat, Integer, Hex", which will now be obeyed
  5051. // by such assignments when it wasn't before.
  5052. )) )
  5053. {
  5054. if ( !(new_arg[arg_index].postfix = (ExprTokenType *)SimpleHeap::Malloc(sizeof(__int64))) )
  5055. return ScriptError(ERR_OUTOFMEM);
  5056. *(__int64 *)new_arg[arg_index].postfix = ATOI64(new_arg[arg_index].text);
  5057. }
  5058. else
  5059. new_arg[arg_index].postfix = NULL; // Indicate that there is no cached binary number.
  5060. }
  5061. break;
  5062. case ACT_LOOP:
  5063. // If possible, determine the type of loop so that the preparser can better
  5064. // validate some things:
  5065. switch (aArgc)
  5066. {
  5067. case 0:
  5068. line.mAttribute = ATTR_LOOP_NORMAL;
  5069. break;
  5070. case 1: // With only 1 arg, it must be a normal loop, file-pattern loop, or registry loop.
  5071. // v1.0.43.07: Added check for new_arg[0].is_expression so that an expression without any variables
  5072. // it it works (e.g. Loop % 1+1):
  5073. if (line.ArgHasDeref(1) || new_arg[0].is_expression) // Impossible to know now what type of loop (only at runtime).
  5074. line.mAttribute = ATTR_LOOP_UNKNOWN;
  5075. else
  5076. {
  5077. if (IsPureNumeric(new_raw_arg1, false))
  5078. line.mAttribute = ATTR_LOOP_NORMAL;
  5079. else
  5080. line.mAttribute = line.RegConvertRootKey(new_raw_arg1) ? ATTR_LOOP_REG : ATTR_LOOP_FILEPATTERN;
  5081. }
  5082. break;
  5083. default: // has 2 or more args.
  5084. if (line.ArgHasDeref(1)) // Impossible to know now what type of loop (only at runtime).
  5085. line.mAttribute = ATTR_LOOP_UNKNOWN;
  5086. else if (!stricmp(new_raw_arg1, "Read"))
  5087. line.mAttribute = ATTR_LOOP_READ_FILE;
  5088. else if (!stricmp(new_raw_arg1, "Parse"))
  5089. line.mAttribute = ATTR_LOOP_PARSE;
  5090. else // the 1st arg can either be a Root Key or a File Pattern, depending on the type of loop.
  5091. {
  5092. line.mAttribute = line.RegConvertRootKey(new_raw_arg1) ? ATTR_LOOP_REG : ATTR_LOOP_FILEPATTERN;
  5093. if (line.mAttribute == ATTR_LOOP_FILEPATTERN)
  5094. {
  5095. // Validate whatever we can rather than waiting for runtime validation:
  5096. if (!line.ArgHasDeref(2) && Line::ConvertLoopMode(new_raw_arg2) == FILE_LOOP_INVALID)
  5097. return ScriptError(ERR_PARAM2_INVALID, new_raw_arg2);
  5098. if (*new_raw_arg3 && !line.ArgHasDeref(3))
  5099. if (strlen(new_raw_arg3) > 1 || (*new_raw_arg3 != '0' && *new_raw_arg3 != '1'))
  5100. return ScriptError(ERR_PARAM3_INVALID, new_raw_arg3);
  5101. }
  5102. else // Registry loop.
  5103. {
  5104. if (aArgc > 2 && !line.ArgHasDeref(3) && Line::ConvertLoopMode(new_raw_arg3) == FILE_LOOP_INVALID)
  5105. return ScriptError(ERR_PARAM3_INVALID, new_raw_arg3);
  5106. if (*new_raw_arg4 && !line.ArgHasDeref(4))
  5107. if (strlen(new_raw_arg4) > 1 || (*new_raw_arg4 != '0' && *new_raw_arg4 != '1'))
  5108. return ScriptError(ERR_PARAM4_INVALID, new_raw_arg4);
  5109. }
  5110. }
  5111. }
  5112. break; // Outer switch().
  5113. case ACT_REPEAT: // These types of loops are always "NORMAL".
  5114. line.mAttribute = ATTR_LOOP_NORMAL;
  5115. break;
  5116. case ACT_WHILE: // Lexikos: ATTR_LOOP_WHILE is used to differentiate ACT_WHILE from ACT_LOOP, allowing code to be shared.
  5117. line.mAttribute = ATTR_LOOP_WHILE;
  5118. break;
  5119. // This one alters g_persistent so is present in its entirety (for simplicity) in both SC an non-SC version.
  5120. case ACT_GUI:
  5121. // By design, scripts that use the GUI cmd anywhere are persistent. Doing this here
  5122. // also allows WinMain() to later detect whether this script should become #SingleInstance.
  5123. // Note: Don't directly change g_AllowOnlyOneInstance here in case the remainder of the
  5124. // script-loading process comes across any explicit uses of #SingleInstance, which would
  5125. // override the default set here.
  5126. g_persistent = true;
  5127. #ifndef AUTOHOTKEYSC // For v1.0.35.01, some syntax checking is removed in compiled scripts to reduce their size.
  5128. if (aArgc > 0 && !line.ArgHasDeref(1))
  5129. {
  5130. GuiCommands gui_cmd = line.ConvertGuiCommand(new_raw_arg1);
  5131. switch (gui_cmd)
  5132. {
  5133. case GUI_CMD_INVALID:
  5134. return ScriptError(ERR_PARAM1_INVALID, new_raw_arg1);
  5135. case GUI_CMD_ADD:
  5136. if (aArgc > 1 && !line.ArgHasDeref(2))
  5137. {
  5138. GuiControls control_type;
  5139. if ( !(control_type = line.ConvertGuiControl(new_raw_arg2)) )
  5140. return ScriptError(ERR_PARAM2_INVALID, new_raw_arg2);
  5141. if (control_type == GUI_CONTROL_TREEVIEW && aArgc > 3) // Reserve it for future use such as a tab-indented continuation section that lists the tree hierarchy.
  5142. return ScriptError(ERR_PARAM4_OMIT, new_raw_arg4);
  5143. }
  5144. break;
  5145. case GUI_CMD_CANCEL:
  5146. case GUI_CMD_MINIMIZE:
  5147. case GUI_CMD_MAXIMIZE:
  5148. case GUI_CMD_RESTORE:
  5149. case GUI_CMD_DESTROY:
  5150. case GUI_CMD_DEFAULT:
  5151. case GUI_CMD_OPTIONS:
  5152. if (aArgc > 1)
  5153. return ScriptError("Parameter #2 and beyond should be omitted in this case.", new_raw_arg2);
  5154. break;
  5155. case GUI_CMD_SUBMIT:
  5156. case GUI_CMD_MENU:
  5157. case GUI_CMD_LISTVIEW:
  5158. case GUI_CMD_TREEVIEW:
  5159. case GUI_CMD_FLASH:
  5160. if (aArgc > 2)
  5161. return ScriptError("Parameter #3 and beyond should be omitted in this case.", new_raw_arg3);
  5162. break;
  5163. // No action for these since they have a varying number of optional params:
  5164. //case GUI_CMD_SHOW:
  5165. //case GUI_CMD_FONT:
  5166. //case GUI_CMD_MARGIN:
  5167. //case GUI_CMD_TAB:
  5168. //case GUI_CMD_COLOR: No load-time param validation to avoid larger EXE size.
  5169. }
  5170. }
  5171. #endif
  5172. break;
  5173. case ACT_GROUPADD:
  5174. case ACT_GROUPACTIVATE:
  5175. case ACT_GROUPDEACTIVATE:
  5176. case ACT_GROUPCLOSE:
  5177. // For all these, store a pointer to the group to help performance.
  5178. // We create a non-existent group even for ACT_GROUPACTIVATE, ACT_GROUPDEACTIVATE
  5179. // and ACT_GROUPCLOSE because we can't rely on the ACT_GROUPADD commands having
  5180. // been parsed prior to them (e.g. something like "Gosub, DefineGroups" may appear
  5181. // in the auto-execute portion of the script).
  5182. if (!line.ArgHasDeref(1))
  5183. if ( !(line.mAttribute = FindGroup(new_raw_arg1, true)) ) // Create-if-not-found so that performance is enhanced at runtime.
  5184. return FAIL; // The above already displayed the error.
  5185. if (aActionType == ACT_GROUPACTIVATE || aActionType == ACT_GROUPDEACTIVATE)
  5186. {
  5187. if (*new_raw_arg2 && !line.ArgHasDeref(2))
  5188. if (strlen(new_raw_arg2) > 1 || toupper(*new_raw_arg2) != 'R')
  5189. return ScriptError(ERR_PARAM2_INVALID, new_raw_arg2);
  5190. }
  5191. else if (aActionType == ACT_GROUPCLOSE)
  5192. if (*new_raw_arg2 && !line.ArgHasDeref(2))
  5193. if (strlen(new_raw_arg2) > 1 || !strchr("RA", toupper(*new_raw_arg2)))
  5194. return ScriptError(ERR_PARAM2_INVALID, new_raw_arg2);
  5195. break;
  5196. case ACT_SETFORMAT: // Must be done even when AUTOHOTKEYSC is defined so that g_WriteCacheDisabledInt64/Double is properly updated.
  5197. if (aArgc < 1)
  5198. break;
  5199. if (line.ArgHasDeref(1)) // Something like "SetFormat, %Var%, ..."
  5200. {
  5201. // For the following and other sections further below that disable the cache, can't wait until
  5202. // runtime execution encounters SetFormat to disable caching because script might rely on the
  5203. // *default* format being *immediately* written out prior to the script changing SetFormat at
  5204. // some later time.
  5205. g_WriteCacheDisabledInt64 = TRUE;
  5206. g_WriteCacheDisabledDouble = TRUE;
  5207. }
  5208. else
  5209. {
  5210. if (!strnicmp(new_raw_arg1, "Float", 5))
  5211. {
  5212. if (stricmp(new_raw_arg1 + 5, "Fast")) // Cache is left enabled when the new FloatFast/IntegerFast mode is present.
  5213. g_WriteCacheDisabledDouble = TRUE;
  5214. if (aArgc > 1 && !line.ArgHasDeref(2))
  5215. {
  5216. if (!IsPureNumeric(new_raw_arg2, true, false, true, true) // v1.0.46.11: Allow impure numbers to support scientific notation; e.g. 0.6e or 0.6E.
  5217. || strlen(new_raw_arg2) >= sizeof(g->FormatFloat) - 2)
  5218. return ScriptError(ERR_PARAM2_INVALID, new_raw_arg2);
  5219. }
  5220. }
  5221. else if (!strnicmp(new_raw_arg1, "Integer", 7))
  5222. {
  5223. if (stricmp(new_raw_arg1 + 7, "Fast")) // Cache is left enabled when the new FloatFast/IntegerFast mode is present.
  5224. g_WriteCacheDisabledInt64 = TRUE;
  5225. if (aArgc > 1 && !line.ArgHasDeref(2) && toupper(*new_raw_arg2) != 'H' && toupper(*new_raw_arg2) != 'D')
  5226. return ScriptError(ERR_PARAM2_INVALID, new_raw_arg2);
  5227. }
  5228. else
  5229. return ScriptError(ERR_PARAM1_INVALID, new_raw_arg1);
  5230. }
  5231. // Size must be less than sizeof() minus 2 because need room to prepend the '%' and append
  5232. // the 'f' to make it a valid format specifier string:
  5233. break;
  5234. case ACT_STRINGSPLIT: // v1.0.48.04: Moved this section so that it is done even when AUTOHOTKEYSC is defined, because the steps below are necessary for both.
  5235. if (*new_raw_arg1 && !line.ArgHasDeref(1)) // The output array must be a legal name.
  5236. {
  5237. // 1.0.46.10: Fixed to look up ArrayName0 in advance (here at loadtime) so that runtime can
  5238. // know whether it's local or global. This is necessary because only here at loadtime
  5239. // is there any awareness of the current function's list of declared variables (to conserve
  5240. // memory, that list is longer available at runtime).
  5241. char temp_var_name[MAX_VAR_NAME_LENGTH + 10]; // Provide extra room for trailing "0", and to detect names that are too long.
  5242. snprintf(temp_var_name, sizeof(temp_var_name), "%s0", new_raw_arg1);
  5243. if ( !(the_new_line->mAttribute = FindOrAddVar(temp_var_name)) )
  5244. return FAIL; // The above already displayed the error.
  5245. }
  5246. //else it's a dynamic array name. Since that's very rare, just use the old runtime behavior for
  5247. // backward compatibility.
  5248. break;
  5249. #ifndef AUTOHOTKEYSC // For v1.0.35.01, some syntax checking is removed in compiled scripts to reduce their size.
  5250. case ACT_RETURN:
  5251. if (aArgc > 0 && !g->CurrentFunc)
  5252. return ScriptError("Return's parameter should be blank except inside a function.");
  5253. break;
  5254. case ACT_AUTOTRIM:
  5255. case ACT_DETECTHIDDENWINDOWS:
  5256. case ACT_DETECTHIDDENTEXT:
  5257. case ACT_SETSTORECAPSLOCKMODE:
  5258. if (aArgc > 0 && !line.ArgHasDeref(1) && !line.ConvertOnOff(new_raw_arg1))
  5259. return ScriptError(ERR_ON_OFF, new_raw_arg1);
  5260. break;
  5261. case ACT_STRINGCASESENSE:
  5262. if (aArgc > 0 && !line.ArgHasDeref(1) && line.ConvertStringCaseSense(new_raw_arg1) == SCS_INVALID)
  5263. return ScriptError(ERR_ON_OFF_LOCALE, new_raw_arg1);
  5264. break;
  5265. case ACT_SETBATCHLINES:
  5266. if (aArgc > 0 && !line.ArgHasDeref(1))
  5267. {
  5268. if (!strcasestr(new_raw_arg1, "ms") && !IsPureNumeric(new_raw_arg1, true, false)) // For simplicity and due to rarity, new_arg[0].is_expression isn't checked, so a line with no variables or function-calls like "SetBatchLines % 1+1" will be wrongly seen as a syntax error.
  5269. return ScriptError(ERR_PARAM1_INVALID, new_raw_arg1);
  5270. }
  5271. break;
  5272. case ACT_SUSPEND:
  5273. if (aArgc > 0 && !line.ArgHasDeref(1) && !line.ConvertOnOffTogglePermit(new_raw_arg1))
  5274. return ScriptError(ERR_ON_OFF_TOGGLE_PERMIT, new_raw_arg1);
  5275. break;
  5276. case ACT_BLOCKINPUT:
  5277. if (aArgc > 0 && !line.ArgHasDeref(1) && !line.ConvertBlockInput(new_raw_arg1))
  5278. return ScriptError(ERR_PARAM1_INVALID, new_raw_arg1);
  5279. break;
  5280. case ACT_SENDMODE:
  5281. if (aArgc > 0 && !line.ArgHasDeref(1) && line.ConvertSendMode(new_raw_arg1, SM_INVALID) == SM_INVALID)
  5282. return ScriptError(ERR_PARAM1_INVALID, new_raw_arg1);
  5283. break;
  5284. case ACT_PAUSE:
  5285. case ACT_KEYHISTORY:
  5286. if (aArgc > 0 && !line.ArgHasDeref(1) && !line.ConvertOnOffToggle(new_raw_arg1))
  5287. return ScriptError(ERR_ON_OFF_TOGGLE, new_raw_arg1);
  5288. break;
  5289. case ACT_SETNUMLOCKSTATE:
  5290. case ACT_SETSCROLLLOCKSTATE:
  5291. case ACT_SETCAPSLOCKSTATE:
  5292. if (aArgc > 0 && !line.ArgHasDeref(1) && !line.ConvertOnOffAlways(new_raw_arg1))
  5293. return ScriptError(ERR_PARAM1_INVALID, new_raw_arg1);
  5294. break;
  5295. case ACT_STRINGMID:
  5296. if (aArgc > 4 && !line.ArgHasDeref(5) && stricmp(NEW_RAW_ARG5, "L"))
  5297. return ScriptError(ERR_PARAM5_INVALID, NEW_RAW_ARG5);
  5298. break;
  5299. case ACT_STRINGGETPOS:
  5300. if (*new_raw_arg4 && !line.ArgHasDeref(4) && !strchr("LR1", toupper(*new_raw_arg4)))
  5301. return ScriptError(ERR_PARAM4_INVALID, new_raw_arg4);
  5302. break;
  5303. case ACT_REGREAD:
  5304. // The below has two checks in case the user is using the 5-param method with the 5th parameter
  5305. // being blank to indicate that the key's "default" value should be read. For example:
  5306. // RegRead, OutVar, REG_SZ, HKEY_CURRENT_USER, Software\Winamp,
  5307. if (aArgc > 4 || line.RegConvertValueType(new_raw_arg2))
  5308. {
  5309. // The obsolete 5-param method is being used, wherein ValueType is the 2nd param.
  5310. if (*new_raw_arg3 && !line.ArgHasDeref(3) && !line.RegConvertRootKey(new_raw_arg3))
  5311. return ScriptError(ERR_REG_KEY, new_raw_arg3);
  5312. }
  5313. else // 4-param method.
  5314. if (*new_raw_arg2 && !line.ArgHasDeref(2) && !line.RegConvertRootKey(new_raw_arg2))
  5315. return ScriptError(ERR_REG_KEY, new_raw_arg2);
  5316. break;
  5317. case ACT_REGWRITE:
  5318. // Both of these checks require that at least two parameters be present. Otherwise, the command
  5319. // is being used in its registry-loop mode and is validated elsewhere:
  5320. if (aArgc > 1)
  5321. {
  5322. if (*new_raw_arg1 && !line.ArgHasDeref(1) && !line.RegConvertValueType(new_raw_arg1))
  5323. return ScriptError(ERR_REG_VALUE_TYPE, new_raw_arg1);
  5324. if (*new_raw_arg2 && !line.ArgHasDeref(2) && !line.RegConvertRootKey(new_raw_arg2))
  5325. return ScriptError(ERR_REG_KEY, new_raw_arg2);
  5326. }
  5327. break;
  5328. case ACT_REGDELETE:
  5329. if (*new_raw_arg1 && !line.ArgHasDeref(1) && !line.RegConvertRootKey(new_raw_arg1))
  5330. return ScriptError(ERR_REG_KEY, new_raw_arg1);
  5331. break;
  5332. case ACT_SOUNDGET:
  5333. case ACT_SOUNDSET:
  5334. if (aActionType == ACT_SOUNDSET && aArgc > 0 && !line.ArgHasDeref(1))
  5335. {
  5336. // The value of catching syntax errors at load-time seems to outweigh the fact that this check
  5337. // sees a valid no-deref expression such as 300-250 as invalid.
  5338. value_float = ATOF(new_raw_arg1);
  5339. if (value_float < -100 || value_float > 100)
  5340. return ScriptError(ERR_PERCENT, new_raw_arg1);
  5341. }
  5342. if (*new_raw_arg2 && !line.ArgHasDeref(2) && !line.SoundConvertComponentType(new_raw_arg2))
  5343. return ScriptError(ERR_PARAM2_INVALID, new_raw_arg2);
  5344. if (*new_raw_arg3 && !line.ArgHasDeref(3) && line.SoundConvertControlType(new_raw_arg3) == MIXERCONTROL_CONTROLTYPE_INVALID)
  5345. return ScriptError(ERR_PARAM3_INVALID, new_raw_arg3);
  5346. break;
  5347. case ACT_SOUNDSETWAVEVOLUME:
  5348. if (aArgc > 0 && !line.ArgHasDeref(1))
  5349. {
  5350. // The value of catching syntax errors at load-time seems to outweigh the fact that this check
  5351. // sees a valid no-deref expression such as 300-250 as invalid.
  5352. value_float = ATOF(new_raw_arg1);
  5353. if (value_float < -100 || value_float > 100)
  5354. return ScriptError(ERR_PERCENT, new_raw_arg1);
  5355. }
  5356. break;
  5357. case ACT_SOUNDPLAY:
  5358. if (*new_raw_arg2 && !line.ArgHasDeref(2) && stricmp(new_raw_arg2, "wait") && stricmp(new_raw_arg2, "1"))
  5359. return ScriptError(ERR_PARAM2_INVALID, new_raw_arg2);
  5360. break;
  5361. case ACT_PIXELSEARCH:
  5362. case ACT_IMAGESEARCH:
  5363. if (!*new_raw_arg3 || !*new_raw_arg4 || !*NEW_RAW_ARG5 || !*NEW_RAW_ARG6 || !*NEW_RAW_ARG7)
  5364. return ScriptError("Parameters 3 through 7 must not be blank.");
  5365. if (aActionType != ACT_IMAGESEARCH)
  5366. {
  5367. if (*NEW_RAW_ARG8 && !line.ArgHasDeref(8))
  5368. {
  5369. // The value of catching syntax errors at load-time seems to outweigh the fact that this check
  5370. // sees a valid no-deref expression such as 300-200 as invalid.
  5371. value = ATOI(NEW_RAW_ARG8);
  5372. if (value < 0 || value > 255)
  5373. return ScriptError(ERR_PARAM8_INVALID, NEW_RAW_ARG8);
  5374. }
  5375. }
  5376. break;
  5377. case ACT_COORDMODE:
  5378. if (*new_raw_arg1 && !line.ArgHasDeref(1) && !line.ConvertCoordModeAttrib(new_raw_arg1))
  5379. return ScriptError(ERR_PARAM1_INVALID, new_raw_arg1);
  5380. break;
  5381. case ACT_SETDEFAULTMOUSESPEED:
  5382. if (*new_raw_arg1 && !line.ArgHasDeref(1))
  5383. {
  5384. // The value of catching syntax errors at load-time seems to outweigh the fact that this check
  5385. // sees a valid no-deref expression such as 1+2 as invalid.
  5386. value = ATOI(new_raw_arg1);
  5387. if (value < 0 || value > MAX_MOUSE_SPEED)
  5388. return ScriptError(ERR_MOUSE_SPEED, new_raw_arg1);
  5389. }
  5390. break;
  5391. case ACT_MOUSEMOVE:
  5392. if (*new_raw_arg3 && !line.ArgHasDeref(3))
  5393. {
  5394. // The value of catching syntax errors at load-time seems to outweigh the fact that this check
  5395. // sees a valid no-deref expression such as 200-150 as invalid.
  5396. value = ATOI(new_raw_arg3);
  5397. if (value < 0 || value > MAX_MOUSE_SPEED)
  5398. return ScriptError(ERR_MOUSE_SPEED, new_raw_arg3);
  5399. }
  5400. if (*new_raw_arg4 && !line.ArgHasDeref(4) && toupper(*new_raw_arg4) != 'R')
  5401. return ScriptError(ERR_PARAM4_INVALID, new_raw_arg4);
  5402. if (!line.ValidateMouseCoords(new_raw_arg1, new_raw_arg2))
  5403. return ScriptError(ERR_MOUSE_COORD, new_raw_arg1);
  5404. break;
  5405. case ACT_MOUSECLICK:
  5406. if (*NEW_RAW_ARG5 && !line.ArgHasDeref(5))
  5407. {
  5408. // The value of catching syntax errors at load-time seems to outweigh the fact that this check
  5409. // sees a valid no-deref expression such as 200-150 as invalid.
  5410. value = ATOI(NEW_RAW_ARG5);
  5411. if (value < 0 || value > MAX_MOUSE_SPEED)
  5412. return ScriptError(ERR_MOUSE_SPEED, NEW_RAW_ARG5);
  5413. }
  5414. if (*NEW_RAW_ARG6 && !line.ArgHasDeref(6))
  5415. if (strlen(NEW_RAW_ARG6) > 1 || !strchr("UD", toupper(*NEW_RAW_ARG6))) // Up / Down
  5416. return ScriptError(ERR_PARAM6_INVALID, NEW_RAW_ARG6);
  5417. if (*NEW_RAW_ARG7 && !line.ArgHasDeref(7) && toupper(*NEW_RAW_ARG7) != 'R')
  5418. return ScriptError(ERR_PARAM7_INVALID, NEW_RAW_ARG7);
  5419. // Check that the button is valid (e.g. left/right/middle):
  5420. if (*new_raw_arg1 && !line.ArgHasDeref(1) && !line.ConvertMouseButton(new_raw_arg1)) // Treats blank as "Left".
  5421. return ScriptError(ERR_MOUSE_BUTTON, new_raw_arg1);
  5422. if (!line.ValidateMouseCoords(new_raw_arg2, new_raw_arg3))
  5423. return ScriptError(ERR_MOUSE_COORD, new_raw_arg2);
  5424. break;
  5425. case ACT_MOUSECLICKDRAG:
  5426. // Even though we check for blanks here at load-time, we don't bother to do so at runtime
  5427. // (i.e. if a dereferenced var resolved to blank, it will be treated as a zero):
  5428. if (!*new_raw_arg4 || !*NEW_RAW_ARG5)
  5429. return ScriptError("Parameter #4 and 5 required.");
  5430. if (*NEW_RAW_ARG6 && !line.ArgHasDeref(6))
  5431. {
  5432. // The value of catching syntax errors at load-time seems to outweigh the fact that this check
  5433. // sees a valid no-deref expression such as 200-150 as invalid.
  5434. value = ATOI(NEW_RAW_ARG6);
  5435. if (value < 0 || value > MAX_MOUSE_SPEED)
  5436. return ScriptError(ERR_MOUSE_SPEED, NEW_RAW_ARG6);
  5437. }
  5438. if (*NEW_RAW_ARG7 && !line.ArgHasDeref(7) && toupper(*NEW_RAW_ARG7) != 'R')
  5439. return ScriptError(ERR_PARAM7_INVALID, NEW_RAW_ARG7);
  5440. if (!line.ArgHasDeref(1))
  5441. if (!line.ConvertMouseButton(new_raw_arg1, false))
  5442. return ScriptError(ERR_MOUSE_BUTTON, new_raw_arg1);
  5443. if (!line.ValidateMouseCoords(new_raw_arg2, new_raw_arg3))
  5444. return ScriptError(ERR_MOUSE_COORD, new_raw_arg2);
  5445. if (!line.ValidateMouseCoords(new_raw_arg4, NEW_RAW_ARG5))
  5446. return ScriptError(ERR_MOUSE_COORD, new_raw_arg4);
  5447. break;
  5448. case ACT_CONTROLSEND:
  5449. case ACT_CONTROLSENDRAW:
  5450. // Window params can all be blank in this case, but characters to send should
  5451. // be non-blank (but it's ok if its a dereferenced var that resolves to blank
  5452. // at runtime):
  5453. if (!*new_raw_arg2)
  5454. return ScriptError(ERR_PARAM2_REQUIRED);
  5455. break;
  5456. case ACT_CONTROLCLICK:
  5457. // Check that the button is valid (e.g. left/right/middle):
  5458. if (*new_raw_arg4 && !line.ArgHasDeref(4)) // i.e. it's allowed to be blank (defaults to left).
  5459. if (!line.ConvertMouseButton(new_raw_arg4)) // Treats blank as "Left".
  5460. return ScriptError(ERR_MOUSE_BUTTON, new_raw_arg4);
  5461. break;
  5462. case ACT_FILEINSTALL:
  5463. case ACT_FILECOPY:
  5464. case ACT_FILEMOVE:
  5465. case ACT_FILECOPYDIR:
  5466. case ACT_FILEMOVEDIR:
  5467. if (*new_raw_arg3 && !line.ArgHasDeref(3))
  5468. {
  5469. // The value of catching syntax errors at load-time seems to outweigh the fact that this check
  5470. // sees a valid no-deref expression such as 2-1 as invalid.
  5471. value = ATOI(new_raw_arg3);
  5472. bool is_pure_numeric = IsPureNumeric(new_raw_arg3, false, true); // Consider negatives to be non-numeric.
  5473. if (aActionType == ACT_FILEMOVEDIR)
  5474. {
  5475. if (!is_pure_numeric && toupper(*new_raw_arg3) != 'R'
  5476. || is_pure_numeric && value > 2) // IsPureNumeric() already checked if value < 0.
  5477. return ScriptError(ERR_PARAM3_INVALID, new_raw_arg3);
  5478. }
  5479. else
  5480. {
  5481. if (!is_pure_numeric || value > 1) // IsPureNumeric() already checked if value < 0.
  5482. return ScriptError(ERR_PARAM3_INVALID, new_raw_arg3);
  5483. }
  5484. }
  5485. if (aActionType == ACT_FILEINSTALL)
  5486. {
  5487. if (aArgc > 0 && line.ArgHasDeref(1))
  5488. return ScriptError("Must not contain variables.", new_raw_arg1);
  5489. }
  5490. break;
  5491. case ACT_FILEREMOVEDIR:
  5492. if (*new_raw_arg2 && !line.ArgHasDeref(2))
  5493. {
  5494. // The value of catching syntax errors at load-time seems to outweigh the fact that this check
  5495. // sees a valid no-deref expression such as 3-2 as invalid.
  5496. value = ATOI(new_raw_arg2);
  5497. if (!IsPureNumeric(new_raw_arg2, false, true) || value > 1) // IsPureNumeric() prevents negatives.
  5498. return ScriptError(ERR_PARAM2_INVALID, new_raw_arg2);
  5499. }
  5500. break;
  5501. case ACT_FILESETATTRIB:
  5502. if (*new_raw_arg1 && !line.ArgHasDeref(1))
  5503. {
  5504. for (char *cp = new_raw_arg1; *cp; ++cp)
  5505. if (!strchr("+-^RASHNOT", toupper(*cp)))
  5506. return ScriptError(ERR_PARAM1_INVALID, new_raw_arg1);
  5507. }
  5508. // For the next two checks:
  5509. // The value of catching syntax errors at load-time seems to outweigh the fact that this check
  5510. // sees a valid no-deref expression such as 300-200 as invalid.
  5511. if (aArgc > 2 && !line.ArgHasDeref(3) && line.ConvertLoopMode(new_raw_arg3) == FILE_LOOP_INVALID)
  5512. return ScriptError(ERR_PARAM3_INVALID, new_raw_arg3);
  5513. if (*new_raw_arg4 && !line.ArgHasDeref(4))
  5514. if (strlen(new_raw_arg4) > 1 || (*new_raw_arg4 != '0' && *new_raw_arg4 != '1'))
  5515. return ScriptError(ERR_PARAM4_INVALID, new_raw_arg4);
  5516. break;
  5517. case ACT_FILEGETTIME:
  5518. if (*new_raw_arg3 && !line.ArgHasDeref(3))
  5519. if (strlen(new_raw_arg3) > 1 || !strchr("MCA", toupper(*new_raw_arg3)))
  5520. return ScriptError(ERR_PARAM3_INVALID, new_raw_arg3);
  5521. break;
  5522. case ACT_FILESETTIME:
  5523. if (*new_raw_arg1 && !line.ArgHasDeref(1))
  5524. if (!YYYYMMDDToSystemTime(new_raw_arg1, st, true))
  5525. return ScriptError(ERR_INVALID_DATETIME, new_raw_arg1);
  5526. if (*new_raw_arg3 && !line.ArgHasDeref(3))
  5527. if (strlen(new_raw_arg3) > 1 || !strchr("MCA", toupper(*new_raw_arg3)))
  5528. return ScriptError(ERR_PARAM3_INVALID, new_raw_arg3);
  5529. // For the next two checks:
  5530. // The value of catching syntax errors at load-time seems to outweigh the fact that this check
  5531. // sees a valid no-deref expression such as 300-200 as invalid.
  5532. if (aArgc > 3 && !line.ArgHasDeref(4) && line.ConvertLoopMode(new_raw_arg4) == FILE_LOOP_INVALID)
  5533. return ScriptError(ERR_PARAM4_INVALID, new_raw_arg4);
  5534. if (*NEW_RAW_ARG5 && !line.ArgHasDeref(5))
  5535. if (strlen(NEW_RAW_ARG5) > 1 || (*NEW_RAW_ARG5 != '0' && *NEW_RAW_ARG5 != '1'))
  5536. return ScriptError(ERR_PARAM5_INVALID, NEW_RAW_ARG5);
  5537. break;
  5538. case ACT_FILEGETSIZE:
  5539. if (*new_raw_arg3 && !line.ArgHasDeref(3))
  5540. if (strlen(new_raw_arg3) > 1 || !strchr("BKM", toupper(*new_raw_arg3))) // Allow B=Bytes as undocumented.
  5541. return ScriptError(ERR_PARAM3_INVALID, new_raw_arg3);
  5542. break;
  5543. case ACT_SETTITLEMATCHMODE:
  5544. if (aArgc > 0 && !line.ArgHasDeref(1) && !line.ConvertTitleMatchMode(new_raw_arg1))
  5545. return ScriptError(ERR_TITLEMATCHMODE, new_raw_arg1);
  5546. break;
  5547. case ACT_TRANSFORM:
  5548. if (aArgc > 1 && !line.ArgHasDeref(2))
  5549. {
  5550. // The value of trans_cmd was already set at an earlier stage, but only here can the error
  5551. // for new_raw_arg3 be displayed because only here was it finally possible to call
  5552. // ArgHasDeref() [above].
  5553. if (trans_cmd == TRANS_CMD_INVALID)
  5554. return ScriptError(ERR_PARAM2_INVALID, new_raw_arg2);
  5555. if (trans_cmd == TRANS_CMD_UNICODE && !*line.mArg[0].text) // blank text means output-var is not a dynamically built one.
  5556. {
  5557. // If the output var isn't the clipboard, the mode is "retrieve clipboard text as UTF-8".
  5558. // Therefore, Param#3 should be blank in that case to avoid unnecessary fetching of the
  5559. // entire clipboard contents as plain text when in fact the command itself will be
  5560. // directly accessing the clipboard rather than relying on the automatic parameter and
  5561. // deref handling.
  5562. if (VAR(line.mArg[0])->Type() == VAR_CLIPBOARD)
  5563. {
  5564. if (aArgc < 3)
  5565. return ScriptError("Parameter #3 must not be blank in this case.");
  5566. }
  5567. else
  5568. if (aArgc > 2)
  5569. return ScriptError(ERR_PARAM3_MUST_BE_BLANK, new_raw_arg3);
  5570. break; // This type has been fully checked above.
  5571. }
  5572. // The value of catching syntax errors at load-time seems to outweigh the fact that this check
  5573. // sees a valid no-deref expression such as 1+2 as invalid.
  5574. if (!line.ArgHasDeref(3)) // "true" since it might have been made into an InputVar due to being a simple expression.
  5575. {
  5576. switch(trans_cmd)
  5577. {
  5578. case TRANS_CMD_CHR:
  5579. case TRANS_CMD_BITNOT:
  5580. case TRANS_CMD_BITSHIFTLEFT:
  5581. case TRANS_CMD_BITSHIFTRIGHT:
  5582. case TRANS_CMD_BITAND:
  5583. case TRANS_CMD_BITOR:
  5584. case TRANS_CMD_BITXOR:
  5585. if (!IsPureNumeric(new_raw_arg3, true, false))
  5586. return ScriptError("Parameter #3 must be an integer in this case.", new_raw_arg3);
  5587. break;
  5588. case TRANS_CMD_MOD:
  5589. case TRANS_CMD_EXP:
  5590. case TRANS_CMD_ROUND:
  5591. case TRANS_CMD_CEIL:
  5592. case TRANS_CMD_FLOOR:
  5593. case TRANS_CMD_ABS:
  5594. case TRANS_CMD_SIN:
  5595. case TRANS_CMD_COS:
  5596. case TRANS_CMD_TAN:
  5597. case TRANS_CMD_ASIN:
  5598. case TRANS_CMD_ACOS:
  5599. case TRANS_CMD_ATAN:
  5600. if (!IsPureNumeric(new_raw_arg3, true, false, true))
  5601. return ScriptError("Parameter #3 must be a number in this case.", new_raw_arg3);
  5602. break;
  5603. case TRANS_CMD_POW:
  5604. case TRANS_CMD_SQRT:
  5605. case TRANS_CMD_LOG:
  5606. case TRANS_CMD_LN:
  5607. if (!IsPureNumeric(new_raw_arg3, false, false, true))
  5608. return ScriptError("Parameter #3 must be a positive integer in this case.", new_raw_arg3);
  5609. break;
  5610. // The following are not listed above because no validation of Parameter #3 is needed at this stage:
  5611. // TRANS_CMD_ASC
  5612. // TRANS_CMD_UNICODE
  5613. // TRANS_CMD_HTML
  5614. // TRANS_CMD_DEREF
  5615. }
  5616. }
  5617. switch(trans_cmd)
  5618. {
  5619. case TRANS_CMD_ASC:
  5620. case TRANS_CMD_CHR:
  5621. case TRANS_CMD_DEREF:
  5622. case TRANS_CMD_UNICODE:
  5623. case TRANS_CMD_HTML:
  5624. case TRANS_CMD_EXP:
  5625. case TRANS_CMD_SQRT:
  5626. case TRANS_CMD_LOG:
  5627. case TRANS_CMD_LN:
  5628. case TRANS_CMD_CEIL:
  5629. case TRANS_CMD_FLOOR:
  5630. case TRANS_CMD_ABS:
  5631. case TRANS_CMD_SIN:
  5632. case TRANS_CMD_COS:
  5633. case TRANS_CMD_TAN:
  5634. case TRANS_CMD_ASIN:
  5635. case TRANS_CMD_ACOS:
  5636. case TRANS_CMD_ATAN:
  5637. case TRANS_CMD_BITNOT:
  5638. if (*new_raw_arg4)
  5639. return ScriptError(ERR_PARAM4_OMIT, new_raw_arg4);
  5640. break;
  5641. case TRANS_CMD_BITAND:
  5642. case TRANS_CMD_BITOR:
  5643. case TRANS_CMD_BITXOR:
  5644. if (!line.ArgHasDeref(4) && !IsPureNumeric(new_raw_arg4, true, false))
  5645. return ScriptError("Parameter #4 must be an integer in this case.", new_raw_arg4);
  5646. break;
  5647. case TRANS_CMD_BITSHIFTLEFT:
  5648. case TRANS_CMD_BITSHIFTRIGHT:
  5649. if (!line.ArgHasDeref(4) && !IsPureNumeric(new_raw_arg4, false, false))
  5650. return ScriptError("Parameter #4 must be a positive integer in this case.", new_raw_arg4);
  5651. break;
  5652. case TRANS_CMD_ROUND:
  5653. if (*new_raw_arg4 && !line.ArgHasDeref(4) && !IsPureNumeric(new_raw_arg4, true, false))
  5654. return ScriptError("Parameter #4 must be blank or an integer in this case.", new_raw_arg4);
  5655. break;
  5656. case TRANS_CMD_MOD:
  5657. case TRANS_CMD_POW:
  5658. if (!line.ArgHasDeref(4) && !IsPureNumeric(new_raw_arg4, true, false, true))
  5659. return ScriptError("Parameter #4 must be a number in this case.", new_raw_arg4);
  5660. break;
  5661. #ifdef _DEBUG
  5662. default:
  5663. return ScriptError("DEBUG: Unhandled", new_raw_arg2); // To improve maintainability.
  5664. #endif
  5665. }
  5666. switch(trans_cmd)
  5667. {
  5668. case TRANS_CMD_CHR:
  5669. if (!line.ArgHasDeref(3))
  5670. {
  5671. value = ATOI(new_raw_arg3);
  5672. if (!IsPureNumeric(new_raw_arg3, false, false) || value > 255) // IsPureNumeric() checks for value < 0 too.
  5673. return ScriptError(ERR_PARAM3_INVALID, new_raw_arg3);
  5674. }
  5675. break;
  5676. case TRANS_CMD_MOD:
  5677. if (!line.ArgHasDeref(4) && !ATOF(new_raw_arg4)) // Parameter is omitted or something that resolves to zero.
  5678. return ScriptError(ERR_DIVIDEBYZERO, new_raw_arg4);
  5679. break;
  5680. }
  5681. }
  5682. break;
  5683. case ACT_MENU:
  5684. if (aArgc > 1 && !line.ArgHasDeref(2))
  5685. {
  5686. MenuCommands menu_cmd = line.ConvertMenuCommand(new_raw_arg2);
  5687. switch(menu_cmd)
  5688. {
  5689. case MENU_CMD_TIP:
  5690. case MENU_CMD_ICON:
  5691. case MENU_CMD_NOICON:
  5692. case MENU_CMD_MAINWINDOW:
  5693. case MENU_CMD_NOMAINWINDOW:
  5694. case MENU_CMD_CLICK:
  5695. {
  5696. bool is_tray = true; // Assume true if unknown.
  5697. if (aArgc > 0 && !line.ArgHasDeref(1))
  5698. if (stricmp(new_raw_arg1, "tray"))
  5699. is_tray = false;
  5700. if (!is_tray)
  5701. return ScriptError(ERR_MENUTRAY, new_raw_arg1);
  5702. break;
  5703. }
  5704. }
  5705. switch (menu_cmd)
  5706. {
  5707. case MENU_CMD_INVALID:
  5708. return ScriptError(ERR_PARAM2_INVALID, new_raw_arg2);
  5709. case MENU_CMD_NODEFAULT:
  5710. case MENU_CMD_STANDARD:
  5711. case MENU_CMD_NOSTANDARD:
  5712. case MENU_CMD_DELETEALL:
  5713. case MENU_CMD_NOICON:
  5714. case MENU_CMD_MAINWINDOW:
  5715. case MENU_CMD_NOMAINWINDOW:
  5716. if (*new_raw_arg3 || *new_raw_arg4 || *NEW_RAW_ARG5 || *NEW_RAW_ARG6)
  5717. return ScriptError("Parameter #3 and beyond should be omitted in this case.", new_raw_arg3);
  5718. break;
  5719. case MENU_CMD_RENAME:
  5720. case MENU_CMD_USEERRORLEVEL:
  5721. case MENU_CMD_CHECK:
  5722. case MENU_CMD_UNCHECK:
  5723. case MENU_CMD_TOGGLECHECK:
  5724. case MENU_CMD_ENABLE:
  5725. case MENU_CMD_DISABLE:
  5726. case MENU_CMD_TOGGLEENABLE:
  5727. case MENU_CMD_DEFAULT:
  5728. case MENU_CMD_DELETE:
  5729. case MENU_CMD_TIP:
  5730. case MENU_CMD_CLICK:
  5731. if ( menu_cmd != MENU_CMD_RENAME && (*new_raw_arg4 || *NEW_RAW_ARG5 || *NEW_RAW_ARG6) )
  5732. return ScriptError("Parameter #4 and beyond should be omitted in this case.", new_raw_arg4);
  5733. switch(menu_cmd)
  5734. {
  5735. case MENU_CMD_USEERRORLEVEL:
  5736. case MENU_CMD_TIP:
  5737. case MENU_CMD_DEFAULT:
  5738. case MENU_CMD_DELETE:
  5739. break; // i.e. for commands other than the above, do the default below.
  5740. default:
  5741. if (!*new_raw_arg3)
  5742. return ScriptError("Parameter #3 must not be blank in this case.");
  5743. }
  5744. break;
  5745. // These have a highly variable number of parameters, or are too rarely used
  5746. // to warrant detailed load-time checking, so are not validated here:
  5747. //case MENU_CMD_SHOW:
  5748. //case MENU_CMD_ADD:
  5749. //case MENU_CMD_COLOR:
  5750. //case MENU_CMD_ICON:
  5751. }
  5752. }
  5753. break;
  5754. case ACT_THREAD:
  5755. if (aArgc > 0 && !line.ArgHasDeref(1) && !line.ConvertThreadCommand(new_raw_arg1))
  5756. return ScriptError(ERR_PARAM1_INVALID, new_raw_arg1);
  5757. break;
  5758. case ACT_CONTROL:
  5759. if (aArgc > 0 && !line.ArgHasDeref(1))
  5760. {
  5761. ControlCmds control_cmd = line.ConvertControlCmd(new_raw_arg1);
  5762. switch (control_cmd)
  5763. {
  5764. case CONTROL_CMD_INVALID:
  5765. return ScriptError(ERR_PARAM1_INVALID, new_raw_arg1);
  5766. case CONTROL_CMD_STYLE:
  5767. case CONTROL_CMD_EXSTYLE:
  5768. case CONTROL_CMD_TABLEFT:
  5769. case CONTROL_CMD_TABRIGHT:
  5770. case CONTROL_CMD_ADD:
  5771. case CONTROL_CMD_DELETE:
  5772. case CONTROL_CMD_CHOOSE:
  5773. case CONTROL_CMD_CHOOSESTRING:
  5774. case CONTROL_CMD_EDITPASTE:
  5775. if (control_cmd != CONTROL_CMD_TABLEFT && control_cmd != CONTROL_CMD_TABRIGHT && !*new_raw_arg2)
  5776. return ScriptError("Parameter #2 must not be blank in this case.");
  5777. break;
  5778. default: // All commands except the above should have a blank Value parameter.
  5779. if (*new_raw_arg2)
  5780. return ScriptError(ERR_PARAM2_MUST_BE_BLANK, new_raw_arg2);
  5781. }
  5782. }
  5783. break;
  5784. case ACT_CONTROLGET:
  5785. if (aArgc > 1 && !line.ArgHasDeref(2))
  5786. {
  5787. ControlGetCmds control_get_cmd = line.ConvertControlGetCmd(new_raw_arg2);
  5788. switch (control_get_cmd)
  5789. {
  5790. case CONTROLGET_CMD_INVALID:
  5791. return ScriptError(ERR_PARAM2_INVALID, new_raw_arg2);
  5792. case CONTROLGET_CMD_FINDSTRING:
  5793. case CONTROLGET_CMD_LINE:
  5794. if (!*new_raw_arg3)
  5795. return ScriptError("Parameter #3 must not be blank in this case.");
  5796. break;
  5797. case CONTROLGET_CMD_LIST:
  5798. break; // Simply break for any sub-commands that have an optional parameter 3.
  5799. default: // All commands except the above should have a blank Value parameter.
  5800. if (*new_raw_arg3)
  5801. return ScriptError(ERR_PARAM3_MUST_BE_BLANK, new_raw_arg3);
  5802. }
  5803. }
  5804. break;
  5805. case ACT_GUICONTROL:
  5806. if (!*new_raw_arg2) // ControlID
  5807. return ScriptError(ERR_PARAM2_REQUIRED);
  5808. if (aArgc > 0 && !line.ArgHasDeref(1))
  5809. {
  5810. GuiControlCmds guicontrol_cmd = line.ConvertGuiControlCmd(new_raw_arg1);
  5811. switch (guicontrol_cmd)
  5812. {
  5813. case GUICONTROL_CMD_INVALID:
  5814. return ScriptError(ERR_PARAM1_INVALID, new_raw_arg1);
  5815. case GUICONTROL_CMD_CONTENTS:
  5816. case GUICONTROL_CMD_TEXT:
  5817. case GUICONTROL_CMD_MOVEDRAW:
  5818. break; // Do nothing for the above commands since Param3 is optional.
  5819. case GUICONTROL_CMD_MOVE:
  5820. case GUICONTROL_CMD_CHOOSE:
  5821. case GUICONTROL_CMD_CHOOSESTRING:
  5822. if (!*new_raw_arg3)
  5823. return ScriptError("Parameter #3 must not be blank in this case.");
  5824. break;
  5825. default: // All commands except the above should have a blank Text parameter.
  5826. if (*new_raw_arg3)
  5827. return ScriptError(ERR_PARAM3_MUST_BE_BLANK, new_raw_arg3);
  5828. }
  5829. }
  5830. break;
  5831. case ACT_GUICONTROLGET:
  5832. if (aArgc > 1 && !line.ArgHasDeref(2))
  5833. {
  5834. GuiControlGetCmds guicontrolget_cmd = line.ConvertGuiControlGetCmd(new_raw_arg2);
  5835. // This first check's error messages take precedence over the next check's:
  5836. switch (guicontrolget_cmd)
  5837. {
  5838. case GUICONTROLGET_CMD_INVALID:
  5839. return ScriptError(ERR_PARAM2_INVALID, new_raw_arg2);
  5840. case GUICONTROLGET_CMD_CONTENTS:
  5841. break; // Do nothing, since Param4 is optional in this case.
  5842. default: // All commands except the above should have a blank parameter here.
  5843. if (*new_raw_arg4) // Currently true for all, since it's a FutureUse param.
  5844. return ScriptError(ERR_PARAM4_MUST_BE_BLANK, new_raw_arg4);
  5845. }
  5846. if (guicontrolget_cmd == GUICONTROLGET_CMD_FOCUS || guicontrolget_cmd == GUICONTROLGET_CMD_FOCUSV)
  5847. {
  5848. if (*new_raw_arg3)
  5849. return ScriptError(ERR_PARAM3_MUST_BE_BLANK, new_raw_arg3);
  5850. }
  5851. // else it can be optionally blank, in which case the output variable is used as the
  5852. // ControlID also.
  5853. }
  5854. break;
  5855. case ACT_DRIVE:
  5856. if (aArgc > 0 && !line.ArgHasDeref(1))
  5857. {
  5858. DriveCmds drive_cmd = line.ConvertDriveCmd(new_raw_arg1);
  5859. if (!drive_cmd)
  5860. return ScriptError(ERR_PARAM1_INVALID, new_raw_arg1);
  5861. if (drive_cmd != DRIVE_CMD_EJECT && !*new_raw_arg2)
  5862. return ScriptError("Parameter #2 must not be blank in this case.");
  5863. // For DRIVE_CMD_LABEL: Note that is is possible and allowed for the new label to be blank.
  5864. // Not currently done since all sub-commands take a mandatory or optional ARG3:
  5865. //if (drive_cmd != ... && *new_raw_arg3)
  5866. // return ScriptError(ERR_PARAM3_MUST_BE_BLANK, new_raw_arg3);
  5867. }
  5868. break;
  5869. case ACT_DRIVEGET:
  5870. if (!line.ArgHasDeref(2)) // Don't check "aArgc > 1" because of DRIVEGET_CMD_SETLABEL's param format.
  5871. {
  5872. DriveGetCmds drive_get_cmd = line.ConvertDriveGetCmd(new_raw_arg2);
  5873. if (!drive_get_cmd)
  5874. return ScriptError(ERR_PARAM2_INVALID, new_raw_arg2);
  5875. if (drive_get_cmd != DRIVEGET_CMD_LIST && drive_get_cmd != DRIVEGET_CMD_STATUSCD && !*new_raw_arg3)
  5876. return ScriptError("Parameter #3 must not be blank in this case.");
  5877. if (drive_get_cmd != DRIVEGET_CMD_SETLABEL && (aArgc < 1 || line.mArg[0].type == ARG_TYPE_NORMAL))
  5878. // The output variable has been omitted.
  5879. return ScriptError("Parameter #1 must not be blank in this case.");
  5880. }
  5881. break;
  5882. case ACT_PROCESS:
  5883. if (aArgc > 0 && !line.ArgHasDeref(1))
  5884. {
  5885. ProcessCmds process_cmd = line.ConvertProcessCmd(new_raw_arg1);
  5886. if (process_cmd != PROCESS_CMD_PRIORITY && process_cmd != PROCESS_CMD_EXIST && !*new_raw_arg2)
  5887. return ScriptError("Parameter #2 must not be blank in this case.");
  5888. switch (process_cmd)
  5889. {
  5890. case PROCESS_CMD_INVALID:
  5891. return ScriptError(ERR_PARAM1_INVALID, new_raw_arg1);
  5892. case PROCESS_CMD_EXIST:
  5893. case PROCESS_CMD_CLOSE:
  5894. if (*new_raw_arg3)
  5895. return ScriptError(ERR_PARAM3_MUST_BE_BLANK, new_raw_arg3);
  5896. break;
  5897. case PROCESS_CMD_PRIORITY:
  5898. if (!*new_raw_arg3 || (!line.ArgHasDeref(3) && !strchr(PROCESS_PRIORITY_LETTERS, toupper(*new_raw_arg3))))
  5899. return ScriptError(ERR_PARAM3_INVALID, new_raw_arg3);
  5900. break;
  5901. case PROCESS_CMD_WAIT:
  5902. case PROCESS_CMD_WAITCLOSE:
  5903. if (*new_raw_arg3 && !line.ArgHasDeref(3) && !IsPureNumeric(new_raw_arg3, false, true, true))
  5904. return ScriptError("If present, parameter #3 must be a positive number in this case.", new_raw_arg3);
  5905. break;
  5906. }
  5907. }
  5908. break;
  5909. // For ACT_WINMOVE, don't validate anything for mandatory args so that its two modes of
  5910. // operation can be supported: 2-param mode and normal-param mode.
  5911. // For these, although we validate that at least one is non-blank here, it's okay at
  5912. // runtime for them all to resolve to be blank, without an error being reported.
  5913. // It's probably more flexible that way since the commands are equipped to handle
  5914. // all-blank params.
  5915. // Not these because they can be used with the "last-used window" mode:
  5916. //case ACT_IFWINEXIST:
  5917. //case ACT_IFWINNOTEXIST:
  5918. // Not these because they can have their window params all-blank to work in "last-used window" mode:
  5919. //case ACT_IFWINACTIVE:
  5920. //case ACT_IFWINNOTACTIVE:
  5921. //case ACT_WINACTIVATE:
  5922. //case ACT_WINWAITCLOSE:
  5923. //case ACT_WINWAITACTIVE:
  5924. //case ACT_WINWAITNOTACTIVE:
  5925. case ACT_WINACTIVATEBOTTOM:
  5926. if (!*new_raw_arg1 && !*new_raw_arg2 && !*new_raw_arg3 && !*new_raw_arg4)
  5927. return ScriptError(ERR_WINDOW_PARAM);
  5928. break;
  5929. case ACT_WINWAIT:
  5930. if (!*new_raw_arg1 && !*new_raw_arg2 && !*new_raw_arg4 && !*NEW_RAW_ARG5) // ARG3 is omitted because it's the timeout.
  5931. return ScriptError(ERR_WINDOW_PARAM);
  5932. break;
  5933. case ACT_WINMENUSELECTITEM:
  5934. // Window params can all be blank in this case, but the first menu param should
  5935. // be non-blank (but it's ok if its a dereferenced var that resolves to blank
  5936. // at runtime):
  5937. if (!*new_raw_arg3)
  5938. return ScriptError(ERR_PARAM3_REQUIRED);
  5939. break;
  5940. case ACT_WINSET:
  5941. if (aArgc > 0 && !line.ArgHasDeref(1))
  5942. {
  5943. switch(line.ConvertWinSetAttribute(new_raw_arg1))
  5944. {
  5945. case WINSET_TRANSPARENT:
  5946. if (aArgc > 1 && !line.ArgHasDeref(2))
  5947. {
  5948. value = ATOI(new_raw_arg2);
  5949. if (value < 0 || value > 255)
  5950. return ScriptError(ERR_PARAM2_INVALID, new_raw_arg2);
  5951. }
  5952. break;
  5953. case WINSET_TRANSCOLOR:
  5954. if (!*new_raw_arg2)
  5955. return ScriptError("Parameter #2 must not be blank in this case.");
  5956. break;
  5957. case WINSET_ALWAYSONTOP:
  5958. if (aArgc > 1 && !line.ArgHasDeref(2) && !line.ConvertOnOffToggle(new_raw_arg2))
  5959. return ScriptError(ERR_ON_OFF_TOGGLE, new_raw_arg2);
  5960. break;
  5961. case WINSET_BOTTOM:
  5962. case WINSET_TOP:
  5963. case WINSET_REDRAW:
  5964. case WINSET_ENABLE:
  5965. case WINSET_DISABLE:
  5966. if (*new_raw_arg2)
  5967. return ScriptError(ERR_PARAM2_MUST_BE_BLANK);
  5968. break;
  5969. case WINSET_INVALID:
  5970. return ScriptError(ERR_PARAM1_INVALID, new_raw_arg1);
  5971. }
  5972. }
  5973. break;
  5974. case ACT_WINGET:
  5975. if (!line.ArgHasDeref(2) && !line.ConvertWinGetCmd(new_raw_arg2)) // It's okay if ARG2 is blank.
  5976. return ScriptError(ERR_PARAM2_INVALID, new_raw_arg2);
  5977. break;
  5978. case ACT_SYSGET:
  5979. if (!line.ArgHasDeref(2) && !line.ConvertSysGetCmd(new_raw_arg2))
  5980. return ScriptError(ERR_PARAM2_INVALID, new_raw_arg2);
  5981. break;
  5982. case ACT_INPUTBOX:
  5983. if (*NEW_RAW_ARG9) // && !line.ArgHasDeref(9)
  5984. return ScriptError("Parameter #9 must be blank.", NEW_RAW_ARG9);
  5985. break;
  5986. case ACT_MSGBOX:
  5987. if (aArgc > 1) // i.e. this MsgBox is using the 3-param or 4-param style.
  5988. if (!line.ArgHasDeref(1)) // i.e. if it's a deref, we won't try to validate it now.
  5989. if (!IsPureNumeric(new_raw_arg1)) // Allow it to be entirely whitespace to indicate 0, like Aut2.
  5990. return ScriptError(ERR_PARAM1_INVALID, new_raw_arg1);
  5991. if (aArgc > 3) // EVEN THOUGH IT'S NUMERIC, due to MsgBox's smart-comma handling, this cannot be an expression because it would never have been detected as the fourth parameter to begin with.
  5992. if (!line.ArgHasDeref(4)) // i.e. if it's a deref, we won't try to validate it now.
  5993. if (!IsPureNumeric(new_raw_arg4, false, true, true))
  5994. return ScriptError(ERR_PARAM4_INVALID, new_raw_arg4);
  5995. break;
  5996. case ACT_IFMSGBOX:
  5997. if (aArgc > 0 && !line.ArgHasDeref(1) && !line.ConvertMsgBoxResult(new_raw_arg1))
  5998. return ScriptError(ERR_PARAM1_INVALID, new_raw_arg1);
  5999. break;
  6000. case ACT_IFIS:
  6001. case ACT_IFISNOT:
  6002. if (aArgc > 1 && !line.ArgHasDeref(2) && !line.ConvertVariableTypeName(new_raw_arg2))
  6003. // Don't refer to it as "Parameter #2" because this command isn't formatted/displayed that way.
  6004. // Update: Param2 is more descriptive than the other (short) alternatives:
  6005. return ScriptError(ERR_PARAM2_INVALID, new_raw_arg2);
  6006. break;
  6007. case ACT_GETKEYSTATE:
  6008. // v1.0.44.03: Don't validate single-character key names because although a character like ü might have no
  6009. // matching VK in system's default layout, that layout could change to something which does have a VK for it.
  6010. if (aArgc > 1 && !line.ArgHasDeref(2) && strlen(new_raw_arg2) > 1 && !TextToVK(new_raw_arg2) && !ConvertJoy(new_raw_arg2))
  6011. return ScriptError(ERR_INVALID_KEY_OR_BUTTON, new_raw_arg2);
  6012. break;
  6013. case ACT_KEYWAIT: // v1.0.44.03: See comment above.
  6014. if (aArgc > 0 && !line.ArgHasDeref(1) && strlen(new_raw_arg1) > 1 && !TextToVK(new_raw_arg1) && !ConvertJoy(new_raw_arg1))
  6015. return ScriptError(ERR_INVALID_KEY_OR_BUTTON, new_raw_arg1);
  6016. break;
  6017. #endif // The above section is in place only if when not AUTOHOTKEYSC.
  6018. }
  6019. if (mNextLineIsFunctionBody)
  6020. {
  6021. mLastFunc->mJumpToLine = the_new_line;
  6022. mNextLineIsFunctionBody = false;
  6023. if (g->CurrentFunc->mDefaultVarType == VAR_DECLARE_NONE)
  6024. g->CurrentFunc->mDefaultVarType = VAR_DECLARE_LOCAL; // Set default since no override was discovered at the top of the body.
  6025. }
  6026. // No checking for unbalanced blocks is done here. That is done by PreparseBlocks() because
  6027. // it displays more informative error messages:
  6028. if (aActionType == ACT_BLOCK_BEGIN)
  6029. {
  6030. ++mCurrentFuncOpenBlockCount; // It's okay to increment unconditionally because it is reset to zero every time a new function definition is entered.
  6031. // It's only necessary to check mLastFunc, not the one(s) that come before it, to see if its
  6032. // mJumpToLine is NULL. This is because our caller has made it impossible for a function
  6033. // to ever have been defined in the first place if it lacked its opening brace. Search on
  6034. // "consecutive function" for more comments. In addition, the following does not check
  6035. // that mCurrentFuncOpenBlockCount is exactly 1, because: 1) Want to be able to support function
  6036. // definitions inside of other function definitions (to help script maintainability); 2) If
  6037. // mCurrentFuncOpenBlockCount is 0 or negative, that will be caught as a syntax error by PreparseBlocks(),
  6038. // which yields a more informative error message that we could here.
  6039. if (mLastFunc && !mLastFunc->mJumpToLine) // If this stmt is true, caller has ensured that g->CurrentFunc isn't NULL.
  6040. {
  6041. // The above check relies upon the fact that mLastFunc->mIsBuiltIn must be false at this stage,
  6042. // which is the case because any non-overridden built-in function won't get added until after all
  6043. // lines have been added, namely PreparseBlocks().
  6044. line.mAttribute = ATTR_TRUE; // Flag this ACT_BLOCK_BEGIN as the opening brace of the function's body.
  6045. // For efficiency, and to prevent ExecUntil from starting a new recursion layer for the function's
  6046. // body, the function's execution should begin at the first line after its open-brace (even if that
  6047. // first line is another open-brace or the function's close-brace (i.e. an empty function):
  6048. mNextLineIsFunctionBody = true;
  6049. }
  6050. }
  6051. else if (aActionType == ACT_BLOCK_END)
  6052. {
  6053. --mCurrentFuncOpenBlockCount; // It's okay to increment unconditionally because it is reset to zero every time a new function definition is entered.
  6054. if (g->CurrentFunc && !mCurrentFuncOpenBlockCount) // Any negative mCurrentFuncOpenBlockCount is caught by a different stage.
  6055. {
  6056. line.mAttribute = ATTR_TRUE; // Flag this ACT_BLOCK_END as the ending brace of a function's body.
  6057. g->CurrentFunc = NULL;
  6058. mFuncExceptionVar = NULL; // Notify FindVar() that there is no exception list to search.
  6059. }
  6060. }
  6061. // Above must be done prior to the below, since it sometimes sets mAttribute for use below.
  6062. ///////////////////////////////////////////////////////////////
  6063. // Update any labels that should refer to the newly added line.
  6064. ///////////////////////////////////////////////////////////////
  6065. // If the label most recently added doesn't yet have an anchor in the script, provide it.
  6066. // UPDATE: In addition, keep searching backward through the labels until a non-NULL
  6067. // mJumpToLine is found. All the ones with a NULL should point to this new line to
  6068. // support cases where one label immediately follows another in the script.
  6069. // Example:
  6070. // #a:: <-- don't leave this label with a NULL jumppoint.
  6071. // LaunchA:
  6072. // ...
  6073. // return
  6074. if (do_update_labels)
  6075. {
  6076. for (Label *label = mLastLabel; label != NULL && label->mJumpToLine == NULL; label = label->mPrevLabel)
  6077. {
  6078. if (line.mActionType == ACT_BLOCK_BEGIN && line.mAttribute == ATTR_TRUE) // Non-zero mAttribute signfies the open-brace of a function body.
  6079. return ScriptError("A label must not point to a function.");
  6080. if (line.mActionType == ACT_ELSE)
  6081. return ScriptError("A label must not point to an ELSE.");
  6082. // Don't allow this because it may cause problems in a case such as this because
  6083. // label1 points to the end-block which is at the same level (and thus normally
  6084. // an allowable jumppoint) as the goto. But we don't want to allow jumping into
  6085. // a block that belongs to a control structure. In this case, it would probably
  6086. // result in a runtime error when the execution unexpectedly encounters the ELSE
  6087. // after performing the goto:
  6088. // goto, label1
  6089. // if x
  6090. // {
  6091. // ...
  6092. // label1:
  6093. // }
  6094. // else
  6095. // ...
  6096. //
  6097. // An alternate way to deal with the above would be to make each block-end be owned
  6098. // by its block-begin rather than the block that encloses them both.
  6099. if (line.mActionType == ACT_BLOCK_END)
  6100. return ScriptError("A label must not point to the end of a block. For loops, use Continue vs. Goto.");
  6101. label->mJumpToLine = the_new_line;
  6102. }
  6103. }
  6104. ++mLineCount; // Right before returning "success", increment our count.
  6105. return OK;
  6106. }
  6107. ResultType Script::ParseDerefs(char *aArgText, char *aArgMap, DerefType *aDeref, int &aDerefCount)
  6108. // Caller provides modifiable aDerefCount, which might be non-zero to indicate that there are already
  6109. // some items in the aDeref array.
  6110. // Returns FAIL or OK.
  6111. {
  6112. size_t deref_string_length; // So that overflow can be detected, this is not of type DerefLengthType.
  6113. // For each dereference found in aArgText:
  6114. for (int j = 0;; ++j) // Increment to skip over the symbol just found by the inner for().
  6115. {
  6116. // Find next non-literal g_DerefChar:
  6117. for (; aArgText[j] && (aArgText[j] != g_DerefChar || (aArgMap && aArgMap[j])); ++j);
  6118. if (!aArgText[j])
  6119. break;
  6120. // else: Match was found; this is the deref's open-symbol.
  6121. if (aDerefCount >= MAX_DEREFS_PER_ARG)
  6122. return ScriptError(TOO_MANY_REFS, aArgText); // Short msg since so rare.
  6123. DerefType &this_deref = aDeref[aDerefCount]; // For performance.
  6124. this_deref.marker = aArgText + j; // Store the deref's starting location.
  6125. // Find next g_DerefChar, even if it's a literal.
  6126. for (++j; aArgText[j] && aArgText[j] != g_DerefChar; ++j);
  6127. if (!aArgText[j])
  6128. return ScriptError("This parameter contains a variable name missing its ending percent sign.", aArgText);
  6129. // Otherwise: Match was found; this should be the deref's close-symbol.
  6130. if (aArgMap && aArgMap[j]) // But it's mapped as literal g_DerefChar.
  6131. return ScriptError("Invalid `%.", aArgText); // Short msg. since so rare.
  6132. deref_string_length = aArgText + j - this_deref.marker + 1;
  6133. if (deref_string_length == 2) // The percent signs were empty, e.g. %%
  6134. return ScriptError("Empty variable reference (%%).", aArgText); // Short msg. since so rare.
  6135. if (deref_string_length - 2 > MAX_VAR_NAME_LENGTH) // -2 for the opening & closing g_DerefChars
  6136. return ScriptError("Variable name too long.", aArgText); // Short msg. since so rare.
  6137. this_deref.is_function = false;
  6138. this_deref.length = (DerefLengthType)deref_string_length;
  6139. if ( !(this_deref.var = FindOrAddVar(this_deref.marker + 1, this_deref.length - 2)) )
  6140. return FAIL; // The called function already displayed the error.
  6141. ++aDerefCount;
  6142. } // for each dereference.
  6143. return OK;
  6144. }
  6145. ResultType Script::DefineFunc(char *aBuf, Var *aFuncExceptionVar[])
  6146. // Returns OK or FAIL.
  6147. // Caller has already called ValidateName() on the function, and it is known that this valid name
  6148. // is followed immediately by an open-paren. aFuncExceptionVar is the address of an array on
  6149. // the caller's stack that will hold the list of exception variables (those that must be explicitly
  6150. // declared as either local or global) within the body of the function.
  6151. {
  6152. char *param_end, *param_start = strchr(aBuf, '('); // Caller has ensured that this will return non-NULL.
  6153. Func *found_func = FindFunc(aBuf, param_start - aBuf);
  6154. if (found_func)
  6155. {
  6156. if (!found_func->mIsBuiltIn)
  6157. return ScriptError("Duplicate function definition.", aBuf); // Seems more descriptive than "Function already defined."
  6158. else // It's a built-in function that the user wants to override with a custom definition.
  6159. {
  6160. found_func->mIsBuiltIn = false; // Override built-in with custom.
  6161. found_func->mParamCount = 0; // Revert to the default appropriate for non-built-in functions.
  6162. found_func->mMinParams = 0; //
  6163. found_func->mJumpToLine = NULL; // Fixed for v1.0.35.12: Must reset for detection elsewhere.
  6164. g->CurrentFunc = found_func;
  6165. }
  6166. }
  6167. else
  6168. // The value of g->CurrentFunc must be set here rather than by our caller since AddVar(), which we call,
  6169. // relies upon it having been done.
  6170. if ( !(g->CurrentFunc = AddFunc(aBuf, param_start - aBuf, false)) )
  6171. return FAIL; // It already displayed the error.
  6172. mCurrentFuncOpenBlockCount = 0; // v1.0.48.01: Initializing this here makes function definions work properly when they're inside a block.
  6173. Func &func = *g->CurrentFunc; // For performance and convenience.
  6174. int insert_pos;
  6175. size_t param_length, value_length;
  6176. FuncParam param[MAX_FUNCTION_PARAMS];
  6177. int param_count = 0;
  6178. char buf[LINE_SIZE], *target;
  6179. bool param_must_have_default = false;
  6180. for (param_start = omit_leading_whitespace(param_start + 1);;)
  6181. {
  6182. if (*param_start == ')') // No more params.
  6183. break;
  6184. // Must start the search at param_start, not param_start+1, so that something like fn(, x) will be properly handled:
  6185. if ( !*param_start || !(param_end = StrChrAny(param_start, ", \t=)")) ) // Look for first comma, space, tab, =, or close-paren.
  6186. return ScriptError(ERR_MISSING_CLOSE_PAREN, aBuf);
  6187. if (param_count >= MAX_FUNCTION_PARAMS)
  6188. return ScriptError("Too many params.", param_start); // Short msg since so rare.
  6189. FuncParam &this_param = param[param_count]; // For performance and convenience.
  6190. // To enhance syntax error catching, consider ByRef to be a keyword; i.e. that can never be the name
  6191. // of a formal parameter:
  6192. if (this_param.is_byref = !strlicmp(param_start, "ByRef", (UINT)(param_end - param_start))) // ByRef.
  6193. {
  6194. // Omit the ByRef keyword from further consideration:
  6195. param_start = omit_leading_whitespace(param_end);
  6196. if ( !*param_start || !(param_end = StrChrAny(param_start, ", \t=)")) ) // Look for first comma, space, tab, =, or close-paren.
  6197. return ScriptError(ERR_MISSING_CLOSE_PAREN, aBuf);
  6198. }
  6199. if ( !(param_length = param_end - param_start) )
  6200. return ScriptError(ERR_BLANK_PARAM, aBuf); // Reporting aBuf vs. param_start seems more informative since Vicinity isn't shown.
  6201. // This will search for local variables, never globals, by virtue of the fact that this
  6202. // new function's mDefaultVarType is always VAR_DECLARE_NONE at this early stage of its creation:
  6203. if (this_param.var = FindVar(param_start, param_length, &insert_pos)) // Assign.
  6204. return ScriptError("Duplicate parameter.", param_start);
  6205. if ( !(this_param.var = AddVar(param_start, param_length, insert_pos, 2)) ) // Pass 2 as last parameter to mean "it's a local but more specifically a function's parameter".
  6206. return FAIL; // It already displayed the error, including attempts to have reserved names as parameter names.
  6207. // v1.0.35: Check if a default value is specified for this parameter and set up for the next iteration.
  6208. // The following section is similar to that used to support initializers for static variables.
  6209. // So maybe maintain them together.
  6210. this_param.default_type = PARAM_DEFAULT_NONE; // Set default.
  6211. param_start = omit_leading_whitespace(param_end);
  6212. if (*param_start == '=') // This is the default value of the param just added.
  6213. {
  6214. param_start = omit_leading_whitespace(param_start + 1); // Start of the default value.
  6215. if (*param_start == '"') // Quoted literal string, or the empty string.
  6216. {
  6217. // v1.0.46.13: Adde support for quoted/literal strings beyond simply "".
  6218. // The following section is nearly identical to one in ExpandExpression().
  6219. // Find the end of this string literal, noting that a pair of double quotes is
  6220. // a literal double quote inside the string.
  6221. for (target = buf, param_end = param_start + 1;;) // Omit the starting-quote from consideration, and from the resulting/built string.
  6222. {
  6223. if (!*param_end) // No matching end-quote. Probably impossible due to load-time validation.
  6224. return ScriptError(ERR_MISSING_CLOSE_QUOTE, param_start); // Reporting param_start vs. aBuf seems more informative in the case of quoted/literal strings.
  6225. if (*param_end == '"') // And if it's not followed immediately by another, this is the end of it.
  6226. {
  6227. ++param_end;
  6228. if (*param_end != '"') // String terminator or some non-quote character.
  6229. break; // The previous char is the ending quote.
  6230. //else a pair of quotes, which resolves to a single literal quote. So fall through
  6231. // to the below, which will copy of quote character to the buffer. Then this pair
  6232. // is skipped over and the loop continues until the real end-quote is found.
  6233. }
  6234. //else some character other than '\0' or '"'.
  6235. *target++ = *param_end++;
  6236. }
  6237. *target = '\0'; // Terminate it in the buffer.
  6238. // The above has also set param_end for use near the bottom of the loop.
  6239. ConvertEscapeSequences(buf, g_EscapeChar, false); // Raw escape sequences like `n haven't been converted yet, so do it now.
  6240. this_param.default_type = PARAM_DEFAULT_STR;
  6241. this_param.default_str = *buf ? SimpleHeap::Malloc(buf, target-buf) : "";
  6242. }
  6243. else // A default value other than a quoted/literal string.
  6244. {
  6245. if (!(param_end = StrChrAny(param_start, ", \t=)"))) // Somewhat debatable but stricter seems better.
  6246. return ScriptError(ERR_MISSING_COMMA, aBuf); // Reporting aBuf vs. param_start seems more informative since Vicinity isn't shown.
  6247. value_length = param_end - param_start;
  6248. if (value_length > MAX_NUMBER_LENGTH) // Too rare to justify elaborate handling or error reporting.
  6249. value_length = MAX_NUMBER_LENGTH;
  6250. strlcpy(buf, param_start, value_length + 1); // Make a temp copy to simplify the below (especially IsPureNumeric).
  6251. if (!stricmp(buf, "false"))
  6252. {
  6253. this_param.default_type = PARAM_DEFAULT_INT;
  6254. this_param.default_int64 = 0;
  6255. }
  6256. else if (!stricmp(buf, "true"))
  6257. {
  6258. this_param.default_type = PARAM_DEFAULT_INT;
  6259. this_param.default_int64 = 1;
  6260. }
  6261. else // The only things supported other than the above are integers and floats.
  6262. {
  6263. // Vars could be supported here via FindVar(), but only globals ABOVE this point in
  6264. // the script would be supported (since other globals don't exist yet). So it seems
  6265. // best to wait until full/comprehesive support for expressions is studied/designed
  6266. // for both static initializers and parameter-default-values.
  6267. switch(IsPureNumeric(buf, true, false, true))
  6268. {
  6269. case PURE_INTEGER:
  6270. // It's always been somewhat inconsistent that for parameter default values,
  6271. // numbers like 0xFF and 0123 do not preserve their formatting (unlike func(0123)
  6272. // and y:=0xFF, which do preserve it). But for backward compatibility and
  6273. // performance, it seems best to keep it this way.
  6274. this_param.default_type = PARAM_DEFAULT_INT;
  6275. this_param.default_int64 = ATOI64(buf);
  6276. break;
  6277. case PURE_FLOAT:
  6278. this_param.default_type = PARAM_DEFAULT_FLOAT;
  6279. this_param.default_double = ATOF(buf);
  6280. break;
  6281. default: // Not numeric (and also not a quoted string because that was handled earlier).
  6282. return ScriptError("Unsupported parameter default.", aBuf);
  6283. }
  6284. }
  6285. }
  6286. param_must_have_default = true; // For now, all other params after this one must also have default values.
  6287. // Set up for the next iteration:
  6288. param_start = omit_leading_whitespace(param_end);
  6289. }
  6290. else // This parameter does not have a default value specified.
  6291. {
  6292. if (param_must_have_default)
  6293. return ScriptError("Parameter default required.", this_param.var->mName);
  6294. ++func.mMinParams;
  6295. }
  6296. ++param_count;
  6297. if (*param_start != ',' && *param_start != ')') // Something like "fn(a, b c)" (missing comma) would cause this.
  6298. return ScriptError(ERR_MISSING_COMMA, aBuf); // Reporting aBuf vs. param_start seems more informative since Vicinity isn't shown.
  6299. if (*param_start == ',')
  6300. {
  6301. param_start = omit_leading_whitespace(param_start + 1);
  6302. if (*param_start == ')') // If *param_start is ',' it will be caught as an error by the next iteration.
  6303. return ScriptError(ERR_BLANK_PARAM, aBuf); // Reporting aBuf vs. param_start seems more informative since Vicinity isn't shown.
  6304. }
  6305. //else it's ')', in which case the next iteration will handle it.
  6306. // Above has ensured that param_start now points to the next parameter, or ')' if none.
  6307. } // for() each formal parameter.
  6308. if (param_count)
  6309. {
  6310. // Allocate memory only for the actual number of parameters actually present.
  6311. size_t size = param_count * sizeof(param[0]);
  6312. if ( !(func.mParam = (FuncParam *)SimpleHeap::Malloc(size)) )
  6313. return ScriptError(ERR_OUTOFMEM);
  6314. func.mParamCount = param_count;
  6315. memcpy(func.mParam, param, size);
  6316. }
  6317. //else leave func.mParam/mParamCount set to their NULL/0 defaults.
  6318. // Indicate success:
  6319. mFuncExceptionVar = aFuncExceptionVar; // Give mFuncExceptionVar its address, to be used for any var declarations inside this function's body.
  6320. mFuncExceptionVarCount = 0; // Reset in preparation of declarations that appear beneath this function's definition.
  6321. return OK;
  6322. }
  6323. #ifndef AUTOHOTKEYSC
  6324. struct FuncLibrary
  6325. {
  6326. char *path;
  6327. DWORD length;
  6328. };
  6329. Func *Script::FindFuncInLibrary(char *aFuncName, size_t aFuncNameLength, bool &aErrorWasShown)
  6330. // Caller must ensure that aFuncName doesn't already exist as a defined function.
  6331. // If aFuncNameLength is 0, the entire length of aFuncName is used.
  6332. {
  6333. aErrorWasShown = false; // Set default for this output parameter.
  6334. int i;
  6335. char *char_after_last_backslash, *terminate_here;
  6336. DWORD attr;
  6337. #define FUNC_LIB_EXT ".ahk"
  6338. #define FUNC_LIB_EXT_LENGTH 4
  6339. #define FUNC_USER_LIB "\\AutoHotkey\\Lib\\" // Needs leading and trailing backslash.
  6340. #define FUNC_USER_LIB_LENGTH 16
  6341. #define FUNC_STD_LIB "Lib\\" // Needs trailing but not leading backslash.
  6342. #define FUNC_STD_LIB_LENGTH 4
  6343. #define FUNC_LIB_COUNT 2
  6344. static FuncLibrary sLib[FUNC_LIB_COUNT] = {0};
  6345. if (!sLib[0].path) // Allocate & discover paths only upon first use because many scripts won't use anything from the library. This saves a bit of memory and performance.
  6346. {
  6347. for (i = 0; i < FUNC_LIB_COUNT; ++i)
  6348. if ( !(sLib[i].path = SimpleHeap::Malloc(MAX_PATH)) ) // Need MAX_PATH for to allow room for appending each candidate file/function name.
  6349. return NULL; // Due to rarity, simply pass the failure back to caller.
  6350. // DETERMINE PATH TO "USER" LIBRARY:
  6351. FuncLibrary *this_lib = sLib; // For convenience and maintainability.
  6352. this_lib->length = BIV_MyDocuments(this_lib->path, "");
  6353. if (this_lib->length < MAX_PATH-FUNC_USER_LIB_LENGTH)
  6354. {
  6355. strcpy(this_lib->path + this_lib->length, FUNC_USER_LIB);
  6356. this_lib->length += FUNC_USER_LIB_LENGTH;
  6357. }
  6358. else // Insufficient room to build the path name.
  6359. {
  6360. *this_lib->path = '\0'; // Mark this library as disabled.
  6361. this_lib->length = 0; //
  6362. }
  6363. // DETERMINE PATH TO "STANDARD" LIBRARY:
  6364. this_lib = sLib + 1; // For convenience and maintainability.
  6365. GetModuleFileName(NULL, this_lib->path, MAX_PATH); // The full path to the currently-running AutoHotkey.exe.
  6366. char_after_last_backslash = 1 + strrchr(this_lib->path, '\\'); // Should always be found, so failure isn't checked.
  6367. this_lib->length = (DWORD)(char_after_last_backslash - this_lib->path); // The length up to and including the last backslash.
  6368. if (this_lib->length < MAX_PATH-FUNC_STD_LIB_LENGTH)
  6369. {
  6370. strcpy(this_lib->path + this_lib->length, FUNC_STD_LIB);
  6371. this_lib->length += FUNC_STD_LIB_LENGTH;
  6372. }
  6373. else // Insufficient room to build the path name.
  6374. {
  6375. *this_lib->path = '\0'; // Mark this library as disabled.
  6376. this_lib->length = 0; //
  6377. }
  6378. for (i = 0; i < FUNC_LIB_COUNT; ++i)
  6379. {
  6380. attr = GetFileAttributes(sLib[i].path); // Seems to accept directories that have a trailing backslash, which is good because it simplifies the code.
  6381. if (attr == 0xFFFFFFFF || !(attr & FILE_ATTRIBUTE_DIRECTORY)) // Directory doesn't exist or it's a file vs. directory. Relies on short-circuit boolean order.
  6382. {
  6383. *sLib[i].path = '\0'; // Mark this library as disabled.
  6384. sLib[i].length = 0; //
  6385. }
  6386. }
  6387. }
  6388. // Above must ensure that all sLib[].path elements are non-NULL (but they can be "" to indicate "no library").
  6389. if (!aFuncNameLength) // Caller didn't specify, so use the entire string.
  6390. aFuncNameLength = strlen(aFuncName);
  6391. char *dest, *first_underscore, class_name_buf[MAX_VAR_NAME_LENGTH + 1];
  6392. char *naked_filename = aFuncName; // Set up for the first iteration.
  6393. size_t naked_filename_length = aFuncNameLength; //
  6394. for (int second_iteration = 0; second_iteration < 2; ++second_iteration)
  6395. {
  6396. for (i = 0; i < FUNC_LIB_COUNT; ++i)
  6397. {
  6398. if (!*sLib[i].path) // Library is marked disabled, so skip it.
  6399. continue;
  6400. if (sLib[i].length + naked_filename_length >= MAX_PATH-FUNC_LIB_EXT_LENGTH)
  6401. continue; // Path too long to match in this library, but try others.
  6402. dest = (char *)memcpy(sLib[i].path + sLib[i].length, naked_filename, naked_filename_length); // Append the filename to the library path.
  6403. strcpy(dest + naked_filename_length, FUNC_LIB_EXT); // Append the file extension.
  6404. attr = GetFileAttributes(sLib[i].path); // Testing confirms that GetFileAttributes() doesn't support wildcards; which is good because we want filenames containing question marks to be "not found" rather than being treated as a match-pattern.
  6405. if (attr == 0xFFFFFFFF || (attr & FILE_ATTRIBUTE_DIRECTORY)) // File doesn't exist or it's a directory. Relies on short-circuit boolean order.
  6406. continue;
  6407. // Since above didn't "continue", a file exists whose name matches that of the requested function.
  6408. // Before loading/including that file, set the working directory to its folder so that if it uses
  6409. // #Include, it will be able to use more convenient/intuitive relative paths. This is similar to
  6410. // the "#Include DirName" feature.
  6411. // Call SetWorkingDir() vs. SetCurrentDirectory() so that it succeeds even for a root drive like
  6412. // C: that lacks a backslash (see SetWorkingDir() for details).
  6413. terminate_here = sLib[i].path + sLib[i].length - 1; // The trailing backslash in the full-path-name to this library.
  6414. *terminate_here = '\0'; // Temporarily terminate it for use with SetWorkingDir().
  6415. SetWorkingDir(sLib[i].path); // See similar section in the #Include directive.
  6416. *terminate_here = '\\'; // Undo the termination.
  6417. if (!LoadIncludedFile(sLib[i].path, false, false)) // Fix for v1.0.47.05: Pass false for allow-dupe because otherwise, it's possible for a stdlib file to attempt to include itself (especially via the LibNamePrefix_ method) and thus give a misleading "duplicate function" vs. "func does not exist" error message. Obsolete: For performance, pass true for allow-dupe so that it doesn't have to check for a duplicate file (seems too rare to worry about duplicates since by definition, the function doesn't yet exist so it's file shouldn't yet be included).
  6418. {
  6419. aErrorWasShown = true; // Above has just displayed its error (e.g. syntax error in a line, failed to open the include file, etc). So override the default set earlier.
  6420. return NULL;
  6421. }
  6422. if (mIncludeLibraryFunctionsThenExit)
  6423. {
  6424. // For each included library-file, write out two #Include lines:
  6425. // 1) Use #Include in its "change working directory" mode so that any explicit #include directives
  6426. // or FileInstalls inside the library file itself will work consistently and properly.
  6427. // 2) Use #IncludeAgain (to improve performance since no dupe-checking is needed) to include
  6428. // the library file itself.
  6429. // We don't directly append library files onto the main script here because:
  6430. // 1) ahk2exe needs to be able to see and act upon FileInstall and #Include lines (i.e. library files
  6431. // might contain #Include even though it's rare).
  6432. // 2) #IncludeAgain and #Include directives that bring in fragments rather than entire functions or
  6433. // subroutines wouldn't work properly if we resolved such includes in AutoHotkey.exe because they
  6434. // wouldn't be properly interleaved/asynchronous, but instead brought out of their library file
  6435. // and deposited separately/synchronously into the temp-include file by some new logic at the
  6436. // AutoHotkey.exe's code for the #Include directive.
  6437. // 3) ahk2exe prefers to omit comments from included files to minimize size of compiled scripts.
  6438. fprintf(mIncludeLibraryFunctionsThenExit, "#Include %-0.*s\n#IncludeAgain %s\n"
  6439. , sLib[i].length, sLib[i].path, sLib[i].path);
  6440. // Now continue on normally so that our caller can continue looking for syntax errors.
  6441. }
  6442. // Now that a matching filename has been found, it seems best to stop searching here even if that
  6443. // file doesn't actually contain the requested function. This helps library authors catch bugs/typos.
  6444. return FindFunc(aFuncName, aFuncNameLength);
  6445. } // for() each library directory.
  6446. // Now that the first iteration is done, set up for the second one that searches by class/prefix.
  6447. // Notes about ambiguity and naming collisions:
  6448. // By the time it gets to the prefix/class search, it's almost given up. Even if it wrongly finds a
  6449. // match in a filename that isn't really a class, it seems inconsequential because at worst it will
  6450. // still not find the function and will then say "call to nonexistent function". In addition, the
  6451. // ability to customize which libraries are searched is planned. This would allow a publicly
  6452. // distributed script to turn off all libraries except stdlib.
  6453. if ( !(first_underscore = strchr(aFuncName, '_')) ) // No second iteration needed.
  6454. break; // All loops are done because second iteration is the last possible attempt.
  6455. naked_filename_length = first_underscore - aFuncName;
  6456. if (naked_filename_length >= sizeof(class_name_buf)) // Class name too long (probably impossible currently).
  6457. break; // All loops are done because second iteration is the last possible attempt.
  6458. naked_filename = class_name_buf; // Point it to a buffer for use below.
  6459. memcpy(naked_filename, aFuncName, naked_filename_length);
  6460. naked_filename[naked_filename_length] = '\0';
  6461. } // 2-iteration for().
  6462. // Since above didn't return, no match found in any library.
  6463. return NULL;
  6464. }
  6465. #endif
  6466. Func *Script::FindFunc(char *aFuncName, size_t aFuncNameLength)
  6467. // Returns the Function whose name matches aFuncName (which caller has ensured isn't NULL).
  6468. // If it doesn't exist, NULL is returned.
  6469. {
  6470. if (!aFuncNameLength) // Caller didn't specify, so use the entire string.
  6471. aFuncNameLength = strlen(aFuncName);
  6472. // For the below, no error is reported because callers don't want that. Instead, simply return
  6473. // NULL to indicate that names that are illegal or too long are not found. If the caller later
  6474. // tries to add the function, it will get an error then:
  6475. if (aFuncNameLength > MAX_VAR_NAME_LENGTH)
  6476. return NULL;
  6477. // The following copy is made because it allows the name searching to use stricmp() instead of
  6478. // strlicmp(), which close to doubles the performance. The copy includes only the first aVarNameLength
  6479. // characters from aVarName:
  6480. char func_name[MAX_VAR_NAME_LENGTH + 1];
  6481. strlcpy(func_name, aFuncName, aFuncNameLength + 1); // +1 to convert length to size.
  6482. Func *pfunc;
  6483. for (pfunc = mFirstFunc; pfunc; pfunc = pfunc->mNextFunc)
  6484. if (!stricmp(func_name, pfunc->mName)) // lstrcmpi() is not used: 1) avoids breaking exisitng scripts; 2) provides consistent behavior across multiple locales; 3) performance.
  6485. return pfunc; // Match found.
  6486. // Since above didn't return, there is no match. See if it's a built-in function that hasn't yet
  6487. // been added to the function list.
  6488. // Set defaults to be possibly overridden below:
  6489. int min_params = 1;
  6490. int max_params = 1;
  6491. BuiltInFunctionType bif;
  6492. char *suffix = func_name + 3;
  6493. if (!strnicmp(func_name, "LV_", 3)) // As a built-in function, LV_* can only be a ListView function.
  6494. {
  6495. suffix = func_name + 3;
  6496. if (!stricmp(suffix, "GetNext"))
  6497. {
  6498. bif = BIF_LV_GetNextOrCount;
  6499. min_params = 0;
  6500. max_params = 2;
  6501. }
  6502. else if (!stricmp(suffix, "GetCount"))
  6503. {
  6504. bif = BIF_LV_GetNextOrCount;
  6505. min_params = 0; // But leave max at its default of 1.
  6506. }
  6507. else if (!stricmp(suffix, "GetText"))
  6508. {
  6509. bif = BIF_LV_GetText;
  6510. min_params = 2;
  6511. max_params = 3;
  6512. }
  6513. else if (!stricmp(suffix, "Add"))
  6514. {
  6515. bif = BIF_LV_AddInsertModify;
  6516. min_params = 0; // 0 params means append a blank row.
  6517. max_params = 10000; // An arbitrarily high limit that will never realistically be reached.
  6518. }
  6519. else if (!stricmp(suffix, "Insert"))
  6520. {
  6521. bif = BIF_LV_AddInsertModify;
  6522. // Leave min_params at 1. Passing only 1 param to it means "insert a blank row".
  6523. max_params = 10000; // An arbitrarily high limit that will never realistically be reached.
  6524. }
  6525. else if (!stricmp(suffix, "Modify"))
  6526. {
  6527. bif = BIF_LV_AddInsertModify; // Although it shares the same function with "Insert", it can still have its own min/max params.
  6528. min_params = 2;
  6529. max_params = 10000; // An arbitrarily high limit that will never realistically be reached.
  6530. }
  6531. else if (!stricmp(suffix, "Delete"))
  6532. {
  6533. bif = BIF_LV_Delete;
  6534. min_params = 0; // Leave max at its default of 1.
  6535. }
  6536. else if (!stricmp(suffix, "InsertCol"))
  6537. {
  6538. bif = BIF_LV_InsertModifyDeleteCol;
  6539. // Leave min_params at 1 because inserting a blank column ahead of the first column
  6540. // does not seem useful enough to sacrifice the no-parameter mode, which might have
  6541. // potential future uses.
  6542. max_params = 3;
  6543. }
  6544. else if (!stricmp(suffix, "ModifyCol"))
  6545. {
  6546. bif = BIF_LV_InsertModifyDeleteCol;
  6547. min_params = 0;
  6548. max_params = 3;
  6549. }
  6550. else if (!stricmp(suffix, "DeleteCol"))
  6551. bif = BIF_LV_InsertModifyDeleteCol; // Leave min/max set to 1.
  6552. else if (!stricmp(suffix, "SetImageList"))
  6553. {
  6554. bif = BIF_LV_SetImageList;
  6555. max_params = 2; // Leave min at 1.
  6556. }
  6557. else
  6558. return NULL;
  6559. }
  6560. else if (!strnicmp(func_name, "TV_", 3)) // As a built-in function, TV_* can only be a TreeView function.
  6561. {
  6562. suffix = func_name + 3;
  6563. if (!stricmp(suffix, "Add"))
  6564. {
  6565. bif = BIF_TV_AddModifyDelete;
  6566. max_params = 3; // Leave min at its default of 1.
  6567. }
  6568. else if (!stricmp(suffix, "Modify"))
  6569. {
  6570. bif = BIF_TV_AddModifyDelete;
  6571. max_params = 3; // One-parameter mode is "select specified item".
  6572. }
  6573. else if (!stricmp(suffix, "Delete"))
  6574. {
  6575. bif = BIF_TV_AddModifyDelete;
  6576. min_params = 0;
  6577. }
  6578. else if (!stricmp(suffix, "GetParent") || !stricmp(suffix, "GetChild") || !stricmp(suffix, "GetPrev"))
  6579. bif = BIF_TV_GetRelatedItem;
  6580. else if (!stricmp(suffix, "GetCount") || !stricmp(suffix, "GetSelection"))
  6581. {
  6582. bif = BIF_TV_GetRelatedItem;
  6583. min_params = 0;
  6584. max_params = 0;
  6585. }
  6586. else if (!stricmp(suffix, "GetNext")) // Unlike "Prev", Next also supports 0 or 2 parameters.
  6587. {
  6588. bif = BIF_TV_GetRelatedItem;
  6589. min_params = 0;
  6590. max_params = 2;
  6591. }
  6592. else if (!stricmp(suffix, "Get") || !stricmp(suffix, "GetText"))
  6593. {
  6594. bif = BIF_TV_Get;
  6595. min_params = 2;
  6596. max_params = 2;
  6597. }
  6598. else
  6599. return NULL;
  6600. }
  6601. else if (!strnicmp(func_name, "IL_", 3)) // It's an ImageList function.
  6602. {
  6603. suffix = func_name + 3;
  6604. if (!stricmp(suffix, "Create"))
  6605. {
  6606. bif = BIF_IL_Create;
  6607. min_params = 0;
  6608. max_params = 3;
  6609. }
  6610. else if (!stricmp(suffix, "Destroy"))
  6611. {
  6612. bif = BIF_IL_Destroy; // Leave Min/Max set to 1.
  6613. }
  6614. else if (!stricmp(suffix, "Add"))
  6615. {
  6616. bif = BIF_IL_Add;
  6617. min_params = 2;
  6618. max_params = 4;
  6619. }
  6620. else
  6621. return NULL;
  6622. }
  6623. else if (!stricmp(func_name, "SB_SetText"))
  6624. {
  6625. bif = BIF_StatusBar;
  6626. max_params = 3; // Leave min_params at its default of 1.
  6627. }
  6628. else if (!stricmp(func_name, "SB_SetParts"))
  6629. {
  6630. bif = BIF_StatusBar;
  6631. min_params = 0;
  6632. max_params = 255; // 255 params alllows for up to 256 parts, which is SB's max.
  6633. }
  6634. else if (!stricmp(func_name, "SB_SetIcon"))
  6635. {
  6636. bif = BIF_StatusBar;
  6637. max_params = 3; // Leave min_params at its default of 1.
  6638. }
  6639. else if (!stricmp(func_name, "StrLen"))
  6640. bif = BIF_StrLen;
  6641. else if (!stricmp(func_name, "SubStr"))
  6642. {
  6643. bif = BIF_SubStr;
  6644. min_params = 2;
  6645. max_params = 3;
  6646. }
  6647. else if (!stricmp(func_name, "InStr"))
  6648. {
  6649. bif = BIF_InStr;
  6650. min_params = 2;
  6651. max_params = 4;
  6652. }
  6653. else if (!stricmp(func_name, "RegExMatch"))
  6654. {
  6655. bif = BIF_RegEx;
  6656. min_params = 2;
  6657. max_params = 4;
  6658. }
  6659. else if (!stricmp(func_name, "RegExReplace"))
  6660. {
  6661. bif = BIF_RegEx;
  6662. min_params = 2;
  6663. max_params = 6;
  6664. }
  6665. else if (!stricmp(func_name, "GetKeyState"))
  6666. {
  6667. bif = BIF_GetKeyState;
  6668. max_params = 2;
  6669. }
  6670. else if (!stricmp(func_name, "Asc"))
  6671. bif = BIF_Asc;
  6672. else if (!stricmp(func_name, "Chr"))
  6673. bif = BIF_Chr;
  6674. else if (!stricmp(func_name, "NumGet"))
  6675. {
  6676. bif = BIF_NumGet;
  6677. max_params = 3;
  6678. }
  6679. else if (!stricmp(func_name, "NumPut"))
  6680. {
  6681. bif = BIF_NumPut;
  6682. min_params = 2;
  6683. max_params = 4;
  6684. }
  6685. else if (!stricmp(func_name, "IsLabel"))
  6686. bif = BIF_IsLabel;
  6687. else if (!stricmp(func_name, "IsFunc"))
  6688. bif = BIF_IsFunc;
  6689. else if (!stricmp(func_name, "DllCall"))
  6690. {
  6691. bif = BIF_DllCall;
  6692. max_params = 10000; // An arbitrarily high limit that will never realistically be reached.
  6693. }
  6694. else if (!stricmp(func_name, "VarSetCapacity"))
  6695. {
  6696. bif = BIF_VarSetCapacity;
  6697. max_params = 3;
  6698. }
  6699. else if (!stricmp(func_name, "FileExist"))
  6700. bif = BIF_FileExist;
  6701. else if (!stricmp(func_name, "WinExist") || !stricmp(func_name, "WinActive"))
  6702. {
  6703. bif = BIF_WinExistActive;
  6704. min_params = 0;
  6705. max_params = 4;
  6706. }
  6707. else if (!stricmp(func_name, "Round"))
  6708. {
  6709. bif = BIF_Round;
  6710. max_params = 2;
  6711. }
  6712. else if (!stricmp(func_name, "Floor") || !stricmp(func_name, "Ceil"))
  6713. bif = BIF_FloorCeil;
  6714. else if (!stricmp(func_name, "Mod"))
  6715. {
  6716. bif = BIF_Mod;
  6717. min_params = 2;
  6718. max_params = 2;
  6719. }
  6720. else if (!stricmp(func_name, "Abs"))
  6721. bif = BIF_Abs;
  6722. else if (!stricmp(func_name, "Sin"))
  6723. bif = BIF_Sin;
  6724. else if (!stricmp(func_name, "Cos"))
  6725. bif = BIF_Cos;
  6726. else if (!stricmp(func_name, "Tan"))
  6727. bif = BIF_Tan;
  6728. else if (!stricmp(func_name, "ASin") || !stricmp(func_name, "ACos"))
  6729. bif = BIF_ASinACos;
  6730. else if (!stricmp(func_name, "ATan"))
  6731. bif = BIF_ATan;
  6732. else if (!stricmp(func_name, "Exp"))
  6733. bif = BIF_Exp;
  6734. else if (!stricmp(func_name, "Sqrt") || !stricmp(func_name, "Log") || !stricmp(func_name, "Ln"))
  6735. bif = BIF_SqrtLogLn;
  6736. else if (!stricmp(func_name, "OnMessage"))
  6737. {
  6738. bif = BIF_OnMessage;
  6739. max_params = 3; // Leave min at 1.
  6740. // By design, scripts that use OnMessage are persistent by default. Doing this here
  6741. // also allows WinMain() to later detect whether this script should become #SingleInstance.
  6742. // Note: Don't directly change g_AllowOnlyOneInstance here in case the remainder of the
  6743. // script-loading process comes across any explicit uses of #SingleInstance, which would
  6744. // override the default set here.
  6745. g_persistent = true;
  6746. }
  6747. else if (!stricmp(func_name, "RegisterCallback"))
  6748. {
  6749. bif = BIF_RegisterCallback;
  6750. max_params = 4; // Leave min_params at 1.
  6751. }
  6752. else
  6753. return NULL; // Maint: There may be other lines above that also return NULL.
  6754. // Since above didn't return, this is a built-in function that hasn't yet been added to the list.
  6755. // Add it now:
  6756. if ( !(pfunc = AddFunc(func_name, aFuncNameLength, true)) )
  6757. return NULL;
  6758. pfunc->mBIF = bif;
  6759. pfunc->mMinParams = min_params;
  6760. pfunc->mParamCount = max_params;
  6761. return pfunc;
  6762. }
  6763. Func *Script::AddFunc(char *aFuncName, size_t aFuncNameLength, bool aIsBuiltIn)
  6764. // This function should probably not be called by anyone except FindOrAddFunc, which has already done
  6765. // the dupe-checking.
  6766. // Returns the address of the new function or NULL on failure.
  6767. // The caller must already have verified that this isn't a duplicate function.
  6768. {
  6769. if (!aFuncNameLength) // Caller didn't specify, so use the entire string.
  6770. aFuncNameLength = strlen(aFuncName);
  6771. if (aFuncNameLength > MAX_VAR_NAME_LENGTH)
  6772. {
  6773. // Dynamic function-calls such as MyFuncArray%i%() aren't currently supported, so the first
  6774. // item below is commented out:
  6775. // Load-time callers should check for this. But at runtime, it's possible for a dynamically
  6776. // resolved function name to be too long. Note that aFuncName should be the exact variable
  6777. // name and does not need to be truncated to aFuncNameLength whenever this error occurs
  6778. // (i.e. at runtime):
  6779. //if (mIsReadyToExecute) // Runtime error.
  6780. // ScriptError("Function name too long." ERR_ABORT, aFuncName);
  6781. //else
  6782. ScriptError("Function name too long.", aFuncName);
  6783. return NULL;
  6784. }
  6785. // Make a temporary copy that includes only the first aFuncNameLength characters from aFuncName:
  6786. char func_name[MAX_VAR_NAME_LENGTH + 1];
  6787. strlcpy(func_name, aFuncName, aFuncNameLength + 1); // See explanation above. +1 to convert length to size.
  6788. // In the future, it might be best to add another check here to disallow function names that consist
  6789. // entirely of numbers. However, this hasn't been done yet because:
  6790. // 1) Not sure if there will ever be a good enough reason.
  6791. // 2) Even if it's done in the far future, it won't break many scripts (pure-numeric functions should be very rare).
  6792. // 3) Those scripts that are broken are not broken in a bad way because the pre-parser will generate a
  6793. // load-time error, which is easy to fix (unlike runtime errors, which require that part of the script
  6794. // to actually execute).
  6795. if (!Var::ValidateName(func_name, mIsReadyToExecute, DISPLAY_FUNC_ERROR)) // Variable and function names are both validated the same way.
  6796. // Above already displayed error for us. This can happen at loadtime or runtime (e.g. StringSplit).
  6797. return NULL;
  6798. // Allocate some dynamic memory to pass to the constructor:
  6799. char *new_name = SimpleHeap::Malloc(func_name, aFuncNameLength);
  6800. if (!new_name)
  6801. // It already displayed the error for us. These mem errors are so unusual that we're not going
  6802. // to bother varying the error message to include ERR_ABORT if this occurs during runtime.
  6803. return NULL;
  6804. Func *the_new_func = new Func(new_name, aIsBuiltIn);
  6805. if (!the_new_func)
  6806. {
  6807. ScriptError(ERR_OUTOFMEM);
  6808. return NULL;
  6809. }
  6810. // v1.0.47: The following ISN'T done because it would slow down commonly used functions. This is because
  6811. // commonly-called functions like InStr() tend to be added first (since they appear so often throughout
  6812. // the script); thus subsequent lookups are fast if they are kept at the beginning of the list rather
  6813. // than being displaced to the end by all other functions).
  6814. // NOT DONE for the reason above:
  6815. // Unlike most of the other link lists, attach new items at the beginning of the list because
  6816. // that allows the standard/user library feature to perform much better for scripts that have hundreds
  6817. // of functions. This is because functions brought in dynamically from a library will then be at the
  6818. // beginning of the list, which allows the function lookup that immediately follows library-loading to
  6819. // find a match almost immediately.
  6820. if (!mFirstFunc) // The list is empty, so this will be the first and last item.
  6821. mFirstFunc = the_new_func;
  6822. else
  6823. mLastFunc->mNextFunc = the_new_func;
  6824. // This must be done after the above:
  6825. mLastFunc = the_new_func; // There's at least one spot in the code that relies on mLastFunc being the most recently added function.
  6826. return the_new_func;
  6827. }
  6828. size_t Line::ArgIndexLength(int aArgIndex)
  6829. // This function is similar to ArgToInt(), so maintain them together.
  6830. // "ArgLength" is the arg's fully resolved, dereferenced length during runtime.
  6831. // Callers must call this only at times when sArgDeref and sArgVar are defined/meaningful.
  6832. // Caller must ensure that aArgIndex is 0 or greater.
  6833. // ArgLength() was added in v1.0.44.14 to help its callers improve performance by avoiding
  6834. // costly calls to strlen() (which is especially beneficial for huge strings).
  6835. {
  6836. #ifdef _DEBUG
  6837. if (aArgIndex < 0)
  6838. {
  6839. LineError("DEBUG: BAD", WARN);
  6840. aArgIndex = 0; // But let it continue.
  6841. }
  6842. #endif
  6843. if (aArgIndex >= mArgc) // Arg doesn't exist, so don't try accessing sArgVar (unlike sArgDeref, it wouldn't be valid to do so).
  6844. return 0; // i.e. treat it as the empty string.
  6845. // The length is not known and must be calculcated in the following situations:
  6846. // - The arg consists of more than just a single isolated variable name (not possible if the arg is
  6847. // ARG_TYPE_INPUT_VAR).
  6848. // - The arg is a built-in variable, in which case the length isn't known, so it must be derived from
  6849. // the string copied into sArgDeref[] by an earlier stage.
  6850. // - The arg is a normal variable but it's VAR_ATTRIB_BINARY_CLIP. In such cases, our callers do not
  6851. // recognize/support binary-clipboard as binary and want the apparent length of the string returned
  6852. // (i.e. strlen(), which takes into account the position of the first binary zero wherever it may be).
  6853. if (sArgVar[aArgIndex])
  6854. {
  6855. Var &var = *sArgVar[aArgIndex]; // For performance and convenience.
  6856. if ( var.Type() == VAR_NORMAL // This and below ordered for short-circuit performance based on types of input expected from caller.
  6857. && !(g_act[mActionType].MaxParamsAu2WithHighBit & 0x80) // Although the ones that have the highbit set are hereby omitted from the fast method, the nature of almost all of the highbit commands is such that their performance won't be measurably affected. See ArgMustBeDereferenced() for more info.
  6858. && (g_NoEnv || var.HasContents()) // v1.0.46.02: Recognize environment variables (when g_NoEnv==FALSE) by falling through to strlen() for them.
  6859. && &var != g_ErrorLevel ) // Mostly for maintainability because the following situation is very rare: If it's g_ErrorLevel, use the deref version instead because if g_ErrorLevel is an input variable in the caller's command, and the caller changes ErrorLevel (such as to set a default) prior to calling this function, the changed/new ErrorLevel will be used rather than its original value (which is usually undesirable).
  6860. //&& !var.IsBinaryClip()) // This check isn't necessary because the line below handles it.
  6861. return var.LengthIgnoreBinaryClip(); // Do it the fast way (unless it's binary clipboard, in which case this call will internally call strlen()).
  6862. }
  6863. // Otherwise, length isn't known due to no variable, a built-in variable, or an environment variable.
  6864. // So do it the slow way.
  6865. return strlen(sArgDeref[aArgIndex]);
  6866. }
  6867. __int64 Line::ArgIndexToInt64(int aArgIndex)
  6868. // This function is similar to ArgIndexLength(), so maintain them together.
  6869. // Callers must call this only at times when sArgDeref and sArgVar are defined/meaningful.
  6870. // Caller must ensure that aArgIndex is 0 or greater.
  6871. {
  6872. #ifdef _DEBUG
  6873. if (aArgIndex < 0)
  6874. {
  6875. LineError("DEBUG: BAD", WARN);
  6876. aArgIndex = 0; // But let it continue.
  6877. }
  6878. #endif
  6879. if (aArgIndex >= mArgc) // See ArgIndexLength() for comments.
  6880. return 0; // i.e. treat it as ATOI64("").
  6881. // SEE THIS POSITION IN ArgIndexLength() FOR IMPORTANT COMMENTS ABOUT THE BELOW.
  6882. if (sArgVar[aArgIndex])
  6883. {
  6884. Var &var = *sArgVar[aArgIndex];
  6885. if ( var.Type() == VAR_NORMAL // See ArgIndexLength() for comments about this line and below.
  6886. && !(g_act[mActionType].MaxParamsAu2WithHighBit & 0x80)
  6887. && (g_NoEnv || var.HasContents())
  6888. && &var != g_ErrorLevel
  6889. && !var.IsBinaryClip() )
  6890. return var.ToInt64(FALSE);
  6891. }
  6892. // Otherwise:
  6893. return ATOI64(sArgDeref[aArgIndex]); // See ArgIndexLength() for comments.
  6894. }
  6895. double Line::ArgIndexToDouble(int aArgIndex)
  6896. // This function is similar to ArgIndexLength(), so maintain them together.
  6897. // Callers must call this only at times when sArgDeref and sArgVar are defined/meaningful.
  6898. // Caller must ensure that aArgIndex is 0 or greater.
  6899. {
  6900. #ifdef _DEBUG
  6901. if (aArgIndex < 0)
  6902. {
  6903. LineError("DEBUG: BAD", WARN);
  6904. aArgIndex = 0; // But let it continue.
  6905. }
  6906. #endif
  6907. if (aArgIndex >= mArgc) // See ArgIndexLength() for comments.
  6908. return 0.0; // i.e. treat it as ATOF("").
  6909. // SEE THIS POSITION IN ARGLENGTH() FOR IMPORTANT COMMENTS ABOUT THE BELOW.
  6910. if (sArgVar[aArgIndex])
  6911. {
  6912. Var &var = *sArgVar[aArgIndex];
  6913. if ( var.Type() == VAR_NORMAL // See ArgIndexLength() for comments about this line and below.
  6914. && !(g_act[mActionType].MaxParamsAu2WithHighBit & 0x80)
  6915. && (g_NoEnv || var.HasContents())
  6916. && &var != g_ErrorLevel
  6917. && !var.IsBinaryClip() )
  6918. return var.ToDouble(FALSE);
  6919. }
  6920. // Otherwise:
  6921. return ATOF(sArgDeref[aArgIndex]); // See ArgIndexLength() for comments.
  6922. }
  6923. Var *Line::ResolveVarOfArg(int aArgIndex, bool aCreateIfNecessary)
  6924. // Returns NULL on failure. Caller has ensured that none of this arg's derefs are function-calls.
  6925. // Args that are input or output variables are normally resolved at load-time, so that
  6926. // they contain a pointer to their Var object. This is done for performance. However,
  6927. // in order to support dynamically resolved variables names like AutoIt2 (e.g. arrays),
  6928. // we have to do some extra work here at runtime.
  6929. // Callers specify false for aCreateIfNecessary whenever the contents of the variable
  6930. // they're trying to find is unimportant. For example, dynamically built input variables,
  6931. // such as "StringLen, length, array%i%", do not need to be created if they weren't
  6932. // previously assigned to (i.e. they weren't previously used as an output variable).
  6933. // In the above example, the array element would never be created here. But if the output
  6934. // variable were dynamic, our call would have told us to create it.
  6935. {
  6936. // The requested ARG isn't even present, so it can't have a variable. Currently, this should
  6937. // never happen because the loading procedure ensures that input/output args are not marked
  6938. // as variables if they are blank (and our caller should check for this and not call in that case):
  6939. if (aArgIndex >= mArgc)
  6940. return NULL;
  6941. ArgStruct &this_arg = mArg[aArgIndex]; // For performance and convenience.
  6942. // Since this function isn't inline (since it's called so frequently), there isn't that much more
  6943. // overhead to doing this check, even though it shouldn't be needed since it's the caller's
  6944. // responsibility:
  6945. if (this_arg.type == ARG_TYPE_NORMAL) // Arg isn't an input or output variable.
  6946. return NULL;
  6947. if (!*this_arg.text) // The arg's variable is not one that needs to be dynamically resolved.
  6948. return VAR(this_arg); // Return the var's address that was already determined at load-time.
  6949. // The above might return NULL in the case where the arg is optional (i.e. the command allows
  6950. // the var name to be omitted). But in that case, the caller should either never have called this
  6951. // function or should check for NULL upon return. UPDATE: This actually never happens, see
  6952. // comment above the "if (aArgIndex >= mArgc)" line.
  6953. // Static to correspond to the static empty_var further below. It needs the memory area
  6954. // to support resolving dynamic environment variables. In the following example,
  6955. // the result will be blank unless the first line is present (without this fix here):
  6956. //null = %SystemRoot% ; bogus line as a required workaround in versions prior to v1.0.16
  6957. //thing = SystemRoot
  6958. //StringTrimLeft, output, %thing%, 0
  6959. //msgbox %output%
  6960. static char sVarName[MAX_VAR_NAME_LENGTH + 1]; // Will hold the dynamically built name.
  6961. // At this point, we know the requested arg is a variable that must be dynamically resolved.
  6962. // This section is similar to that in ExpandArg(), so they should be maintained together:
  6963. char *pText = this_arg.text; // Start at the begining of this arg's text.
  6964. int var_name_length = 0;
  6965. if (this_arg.deref) // There's at least one deref.
  6966. {
  6967. // Caller has ensured that none of these derefs are function calls (i.e. deref->is_function is alway false).
  6968. for (DerefType *deref = this_arg.deref // Start off by looking for the first deref.
  6969. ; deref->marker; ++deref) // A deref with a NULL marker terminates the list.
  6970. {
  6971. // FOR EACH DEREF IN AN ARG (if we're here, there's at least one):
  6972. // Copy the chars that occur prior to deref->marker into the buffer:
  6973. for (; pText < deref->marker && var_name_length < MAX_VAR_NAME_LENGTH; sVarName[var_name_length++] = *pText++);
  6974. if (var_name_length >= MAX_VAR_NAME_LENGTH && pText < deref->marker) // The variable name would be too long!
  6975. {
  6976. // This type of error is just a warning because this function isn't set up to cause a true
  6977. // failure. This is because the use of dynamically named variables is rare, and only for
  6978. // people who should know what they're doing. In any case, when the caller of this
  6979. // function called it to resolve an output variable, it will see tha the result is
  6980. // NULL and terminate the current subroutine.
  6981. #define DYNAMIC_TOO_LONG "This dynamically built variable name is too long." \
  6982. " If this variable was not intended to be dynamic, remove the % symbols from it."
  6983. LineError(DYNAMIC_TOO_LONG, FAIL, this_arg.text);
  6984. return NULL;
  6985. }
  6986. // Now copy the contents of the dereferenced var. For all cases, aBuf has already
  6987. // been verified to be large enough, assuming the value hasn't changed between the
  6988. // time we were called and the time the caller calculated the space needed.
  6989. if (deref->var->Get() > (VarSizeType)(MAX_VAR_NAME_LENGTH - var_name_length)) // The variable name would be too long!
  6990. {
  6991. LineError(DYNAMIC_TOO_LONG, FAIL, this_arg.text);
  6992. return NULL;
  6993. }
  6994. var_name_length += deref->var->Get(sVarName + var_name_length);
  6995. // Finally, jump over the dereference text. Note that in the case of an expression, there might not
  6996. // be any percent signs within the text of the dereference, e.g. x + y, not %x% + %y%.
  6997. pText += deref->length;
  6998. }
  6999. }
  7000. // Copy any chars that occur after the final deref into the buffer:
  7001. for (; *pText && var_name_length < MAX_VAR_NAME_LENGTH; sVarName[var_name_length++] = *pText++);
  7002. if (var_name_length >= MAX_VAR_NAME_LENGTH && *pText) // The variable name would be too long!
  7003. {
  7004. LineError(DYNAMIC_TOO_LONG, FAIL, this_arg.text);
  7005. return NULL;
  7006. }
  7007. if (!var_name_length)
  7008. {
  7009. LineError("This dynamic variable is blank. If this variable was not intended to be dynamic,"
  7010. " remove the % symbols from it.", FAIL, this_arg.text);
  7011. return NULL;
  7012. }
  7013. // Terminate the buffer, even if nothing was written into it:
  7014. sVarName[var_name_length] = '\0';
  7015. static Var empty_var(sVarName, (void *)VAR_NORMAL, false); // Must use sVarName here. See comment above for why.
  7016. Var *found_var;
  7017. if (!aCreateIfNecessary)
  7018. {
  7019. // Now we've dynamically build the variable name. It's possible that the name is illegal,
  7020. // so check that (the name is automatically checked by FindOrAddVar(), so we only need to
  7021. // check it if we're not calling that):
  7022. if (!Var::ValidateName(sVarName, g_script.mIsReadyToExecute))
  7023. return NULL; // Above already displayed error for us.
  7024. // The use of ALWAYS_PREFER_LOCAL below improves flexibility of assume-global functions
  7025. // by allowing this command to resolve to a local first if such a local exists:
  7026. if (found_var = g_script.FindVar(sVarName, var_name_length, NULL, ALWAYS_PREFER_LOCAL)) // Assign.
  7027. return found_var;
  7028. // At this point, this is either a non-existent variable or a reserved/built-in variable
  7029. // that was never statically referenced in the script (only dynamically), e.g. A_IPAddress%A_Index%
  7030. if (Script::GetVarType(sVarName) == (void *)VAR_NORMAL)
  7031. // If not found: for performance reasons, don't create it because caller just wants an empty variable.
  7032. return &empty_var;
  7033. //else it's the clipboard or some other built-in variable, so continue onward so that the
  7034. // variable gets created in the variable list, which is necessary to allow it to be properly
  7035. // dereferenced, e.g. in a script consisting of only the following:
  7036. // Loop, 4
  7037. // StringTrimRight, IP, A_IPAddress%A_Index%, 0
  7038. }
  7039. // Otherwise, aCreateIfNecessary is true or we want to create this variable unconditionally for the
  7040. // reason described above. ALWAYS_PREFER_LOCAL is used so that any existing local variable will
  7041. // take precedence over a global of the same name when assume-global is in effect. If neither type
  7042. // of variable exists, a global variable will be created if assume-global is in effect.
  7043. if ( !(found_var = g_script.FindOrAddVar(sVarName, var_name_length, ALWAYS_PREFER_LOCAL)) )
  7044. return NULL; // Above will already have displayed the error.
  7045. if (this_arg.type == ARG_TYPE_OUTPUT_VAR && VAR_IS_READONLY(*found_var))
  7046. {
  7047. LineError(ERR_VAR_IS_READONLY, FAIL, sVarName);
  7048. return NULL; // Don't return the var, preventing the caller from assigning to it.
  7049. }
  7050. else
  7051. return found_var;
  7052. }
  7053. Var *Script::FindOrAddVar(char *aVarName, size_t aVarNameLength, int aAlwaysUse, bool *apIsException)
  7054. // Caller has ensured that aVarName isn't NULL.
  7055. // Returns the Var whose name matches aVarName. If it doesn't exist, it is created.
  7056. {
  7057. if (!*aVarName)
  7058. return NULL;
  7059. int insert_pos;
  7060. bool is_local; // Used to detect which type of var should be added in case the result of the below is NULL.
  7061. Var *var;
  7062. if (var = FindVar(aVarName, aVarNameLength, &insert_pos, aAlwaysUse, apIsException, &is_local))
  7063. return var;
  7064. // Otherwise, no match found, so create a new var. This will return NULL if there was a problem,
  7065. // in which case AddVar() will already have displayed the error:
  7066. return AddVar(aVarName, aVarNameLength, insert_pos, is_local);
  7067. }
  7068. Var *Script::FindVar(char *aVarName, size_t aVarNameLength, int *apInsertPos, int aAlwaysUse
  7069. , bool *apIsException, bool *apIsLocal)
  7070. // Caller has ensured that aVarName isn't NULL. It must also ignore the contents of apInsertPos when
  7071. // a match (non-NULL value) is returned.
  7072. // Returns the Var whose name matches aVarName. If it doesn't exist, NULL is returned.
  7073. // If caller provided a non-NULL apInsertPos, it will be given a the array index that a newly
  7074. // inserted item should have to keep the list in sorted order (which also allows the ListVars command
  7075. // to display the variables in alphabetical order).
  7076. {
  7077. if (!*aVarName)
  7078. return NULL;
  7079. if (!aVarNameLength) // Caller didn't specify, so use the entire string.
  7080. aVarNameLength = strlen(aVarName);
  7081. // For the below, no error is reported because callers don't want that. Instead, simply return
  7082. // NULL to indicate that names that are illegal or too long are not found. When the caller later
  7083. // tries to add the variable, it will get an error then:
  7084. if (aVarNameLength > MAX_VAR_NAME_LENGTH)
  7085. return NULL;
  7086. // The following copy is made because it allows the various searches below to use stricmp() instead of
  7087. // strlicmp(), which close to doubles their performance. The copy includes only the first aVarNameLength
  7088. // characters from aVarName:
  7089. char var_name[MAX_VAR_NAME_LENGTH + 1];
  7090. strlcpy(var_name, aVarName, aVarNameLength + 1); // +1 to convert length to size.
  7091. global_struct &g = *::g; // Reduces code size and may improve performance.
  7092. Var *found_var = NULL; // Set default.
  7093. bool is_local;
  7094. if (aAlwaysUse == ALWAYS_USE_GLOBAL)
  7095. is_local = false;
  7096. else if (aAlwaysUse == ALWAYS_USE_LOCAL)
  7097. // v1.0.44.10: The following was changed from it's former value of "true" so that places further below
  7098. // (including passing is_local is call to AddVar()) don't have to ensure that g.CurrentFunc!=NULL.
  7099. // This fixes a crash that occured when a caller specified ALWAYS_USE_LOCAL even though the current
  7100. // thread isn't actually inside a *called* function (perhaps meaning things like a timed subroutine
  7101. // that lies inside a "container function").
  7102. // Some callers like SYSGET_CMD_MONITORAREA might try to find/add a local array if they see that their
  7103. // base variable is classified as local (such classification occurs at loadtime, but only for non-dynamic
  7104. // variable references). But the current thread entered a "container function" by means other than a
  7105. // function-call (such as SetTimer), not only is g.CurrentFunc NULL, but there's no easy way to discover
  7106. // which function owns the currently executing line (a means could be added to the class "Var" or "Line"
  7107. // but doesn't seem worth it yet due to performance and memory reduction).
  7108. is_local = (g.CurrentFunc != NULL);
  7109. else if (aAlwaysUse == ALWAYS_PREFER_LOCAL)
  7110. {
  7111. if (g.CurrentFunc) // Caller relies on us to do this final check.
  7112. is_local = true;
  7113. else
  7114. {
  7115. is_local = false;
  7116. aAlwaysUse = ALWAYS_USE_GLOBAL; // Override aAlwaysUse for maintainability, in case there are more references to it below.
  7117. }
  7118. }
  7119. else // aAlwaysUse == ALWAYS_USE_DEFAULT
  7120. {
  7121. is_local = g.CurrentFunc && g.CurrentFunc->mDefaultVarType != VAR_DECLARE_GLOBAL; // i.e. ASSUME_LOCAL or ASSUME_NONE
  7122. if (mFuncExceptionVar) // Caller has ensured that this non-NULL if and only if g.CurrentFunc is non-NULL.
  7123. {
  7124. int i;
  7125. for (i = 0; i < mFuncExceptionVarCount; ++i)
  7126. {
  7127. if (!stricmp(var_name, mFuncExceptionVar[i]->mName)) // lstrcmpi() is not used: 1) avoids breaking exisitng scripts; 2) provides consistent behavior across multiple locales; 3) performance.
  7128. {
  7129. is_local = !is_local; // Since it's an exception, it's always the opposite of what it would have been.
  7130. found_var = mFuncExceptionVar[i];
  7131. break;
  7132. }
  7133. }
  7134. // The following section is necessary because a function's parameters are not put into the
  7135. // exception list during load-time. Thus, for an assume-global function, these are basically
  7136. // treated as exceptions too.
  7137. // If this function is one that assumes variables are global, the function's parameters are
  7138. // implicitly declared local because parameters are always local:
  7139. // Since the following is inside this block, it is checked only at loadtime. It doesn't need
  7140. // to be checked at runtime because most things that resolve input variables or variables whose
  7141. // contents will be read (as compared to something that tries to create a dynamic variable, such
  7142. // as ResolveVarOfArg() for an output variable) at runtime use the ALWAYS_PREFER_LOCAL flag to
  7143. // indicate that a local of the same name as a global should take precedence. This adds more
  7144. // flexibility/benefit than its costs in terms of confusion because otherwise there would be
  7145. // no way to dynamically reference the local variables of an assume-global function.
  7146. if (g.CurrentFunc->mDefaultVarType == VAR_DECLARE_GLOBAL && !is_local) // g.CurrentFunc is also known to be non-NULL in this case.
  7147. {
  7148. for (i = 0; i < g.CurrentFunc->mParamCount; ++i)
  7149. if (!stricmp(var_name, g.CurrentFunc->mParam[i].var->mName)) // lstrcmpi() is not used: 1) avoids breaking exisitng scripts; 2) provides consistent behavior across multiple locales; 3) performance.
  7150. {
  7151. is_local = true;
  7152. found_var = g.CurrentFunc->mParam[i].var;
  7153. break;
  7154. }
  7155. }
  7156. } // if (there is an exception list)
  7157. } // aAlwaysUse == ALWAYS_USE_DEFAULT
  7158. // Above has ensured that g.CurrentFunc!=NULL whenever is_local==true.
  7159. if (apIsLocal) // Its purpose is to inform caller of type it would have been in case we don't find a match.
  7160. *apIsLocal = is_local; // And it stays this way even if globals will be searched because caller wants that. In other words, a local var is created by default when there is not existing global or local.
  7161. if (apInsertPos) // Set default. Caller should ignore the value when match is found.
  7162. *apInsertPos = -1;
  7163. if (apIsException)
  7164. *apIsException = (found_var != NULL);
  7165. if (found_var) // Match found (as an exception or load-time "is parameter" exception).
  7166. return found_var; // apInsertPos does not need to be set because caller doesn't need it when match is found.
  7167. // Init for binary search loop:
  7168. int left, right, mid, result; // left/right must be ints to allow them to go negative and detect underflow.
  7169. Var **var; // An array of pointers-to-var.
  7170. if (is_local)
  7171. {
  7172. var = g.CurrentFunc->mVar;
  7173. right = g.CurrentFunc->mVarCount - 1;
  7174. }
  7175. else
  7176. {
  7177. var = mVar;
  7178. right = mVarCount - 1;
  7179. }
  7180. // Binary search:
  7181. for (left = 0; left <= right;) // "right" was already initialized above.
  7182. {
  7183. mid = (left + right) / 2;
  7184. result = stricmp(var_name, var[mid]->mName); // lstrcmpi() is not used: 1) avoids breaking exisitng scripts; 2) provides consistent behavior across multiple locales; 3) performance.
  7185. if (result > 0)
  7186. left = mid + 1;
  7187. else if (result < 0)
  7188. right = mid - 1;
  7189. else // Match found.
  7190. return var[mid];
  7191. }
  7192. // Since above didn't return, no match was found in the main list, so search the lazy list if there
  7193. // is one. If there's no lazy list, the value of "left" established above will be used as the
  7194. // insertion point further below:
  7195. if (is_local)
  7196. {
  7197. var = g.CurrentFunc->mLazyVar;
  7198. right = g.CurrentFunc->mLazyVarCount - 1;
  7199. }
  7200. else
  7201. {
  7202. var = mLazyVar;
  7203. right = mLazyVarCount - 1;
  7204. }
  7205. if (var) // There is a lazy list to search (and even if the list is empty, left must be reset to 0 below).
  7206. {
  7207. // Binary search:
  7208. for (left = 0; left <= right;) // "right" was already initialized above.
  7209. {
  7210. mid = (left + right) / 2;
  7211. result = stricmp(var_name, var[mid]->mName); // lstrcmpi() is not used: 1) avoids breaking exisitng scripts; 2) provides consistent behavior across multiple locales; 3) performance.
  7212. if (result > 0)
  7213. left = mid + 1;
  7214. else if (result < 0)
  7215. right = mid - 1;
  7216. else // Match found.
  7217. return var[mid];
  7218. }
  7219. }
  7220. // Since above didn't return, no match was found and "left" always contains the position where aVarName
  7221. // should be inserted to keep the list sorted. The item is always inserted into the lazy list unless
  7222. // there is no lazy list.
  7223. // Set the output parameter, if present:
  7224. if (apInsertPos) // Caller wants this value even if we'll be resorting to searching the global list below.
  7225. *apInsertPos = left; // This is the index a newly inserted item should have to keep alphabetical order.
  7226. // Since no match was found, if this is a local fall back to searching the list of globals at runtime
  7227. // if the caller didn't insist on a particular type:
  7228. if (is_local)
  7229. {
  7230. if (aAlwaysUse == ALWAYS_PREFER_LOCAL)
  7231. {
  7232. // In this case, callers want to fall back to globals when a local wasn't found. However,
  7233. // they want the insertion (if our caller will be doing one) to insert according to the
  7234. // current assume-mode. Therefore, if the mode is assume-global, pass the apIsLocal
  7235. // and apInsertPos variables to FindVar() so that it will update them to be global.
  7236. // Otherwise, do not pass them since they were already set correctly by us above.
  7237. if (g.CurrentFunc->mDefaultVarType == VAR_DECLARE_GLOBAL)
  7238. return FindVar(aVarName, aVarNameLength, apInsertPos, ALWAYS_USE_GLOBAL, NULL, apIsLocal);
  7239. else
  7240. return FindVar(aVarName, aVarNameLength, NULL, ALWAYS_USE_GLOBAL);
  7241. }
  7242. if (aAlwaysUse == ALWAYS_USE_DEFAULT && mIsReadyToExecute) // In this case, fall back to globals only at runtime.
  7243. return FindVar(aVarName, aVarNameLength, NULL, ALWAYS_USE_GLOBAL);
  7244. }
  7245. // Otherwise, since above didn't return:
  7246. return NULL; // No match.
  7247. }
  7248. Var *Script::AddVar(char *aVarName, size_t aVarNameLength, int aInsertPos, int aIsLocal)
  7249. // Returns the address of the new variable or NULL on failure.
  7250. // Caller must ensure that g->CurrentFunc!=NULL whenever aIsLocal==true.
  7251. // Caller must ensure that aVarName isn't NULL and that this isn't a duplicate variable name.
  7252. // In addition, it has provided aInsertPos, which is the insertion point so that the list stays sorted.
  7253. // Finally, aIsLocal has been provided to indicate which list, global or local, should receive this
  7254. // new variable. aIsLocal is normally 0 or 1 (boolean), but it may be 2 to indicate "it's a local AND a
  7255. // function's parameter".
  7256. {
  7257. if (!*aVarName) // Should never happen, so just silently indicate failure.
  7258. return NULL;
  7259. if (!aVarNameLength) // Caller didn't specify, so use the entire string.
  7260. aVarNameLength = strlen(aVarName);
  7261. if (aVarNameLength > MAX_VAR_NAME_LENGTH)
  7262. {
  7263. // Load-time callers should check for this. But at runtime, it's possible for a dynamically
  7264. // resolved variable name to be too long. Note that aVarName should be the exact variable
  7265. // name and does not need to be truncated to aVarNameLength whenever this error occurs
  7266. // (i.e. at runtime):
  7267. if (mIsReadyToExecute) // Runtime error.
  7268. ScriptError("Variable name too long." ERR_ABORT, aVarName);
  7269. else
  7270. ScriptError("Variable name too long.", aVarName);
  7271. return NULL;
  7272. }
  7273. // Make a temporary copy that includes only the first aVarNameLength characters from aVarName:
  7274. char var_name[MAX_VAR_NAME_LENGTH + 1];
  7275. strlcpy(var_name, aVarName, aVarNameLength + 1); // See explanation above. +1 to convert length to size.
  7276. if (!Var::ValidateName(var_name, mIsReadyToExecute))
  7277. // Above already displayed error for us. This can happen at loadtime or runtime (e.g. StringSplit).
  7278. return NULL;
  7279. // Not necessary or desirable to add built-in variables to a function's list of locals. Always keep
  7280. // built-in vars in the global list for efficiency and to keep them out of ListVars. Note that another
  7281. // section at loadtime displays an error for any attempt to explicitly declare built-in variables as
  7282. // either global or local.
  7283. void *var_type = GetVarType(var_name);
  7284. if (aIsLocal && (var_type != (void *)VAR_NORMAL || !stricmp(var_name, "ErrorLevel"))) // Attempt to create built-in variable as local.
  7285. {
  7286. if (aIsLocal == 1) // It's not a UDF's parameter, so fall back to the global built-in variable of this name rather than displaying an error.
  7287. return FindOrAddVar(var_name, aVarNameLength, ALWAYS_USE_GLOBAL); // Force find-or-create of global.
  7288. else // aIsLocal == 2, which means "this is a local variable and a function's parameter".
  7289. {
  7290. ScriptError("Illegal parameter name.", aVarName); // Short message since so rare.
  7291. return NULL;
  7292. }
  7293. }
  7294. // Allocate some dynamic memory to pass to the constructor:
  7295. char *new_name = SimpleHeap::Malloc(var_name, aVarNameLength);
  7296. if (!new_name)
  7297. // It already displayed the error for us. These mem errors are so unusual that we're not going
  7298. // to bother varying the error message to include ERR_ABORT if this occurs during runtime.
  7299. return NULL;
  7300. Var *the_new_var = new Var(new_name, var_type, aIsLocal != 0); // , aAttrib);
  7301. if (the_new_var == NULL)
  7302. {
  7303. ScriptError(ERR_OUTOFMEM);
  7304. return NULL;
  7305. }
  7306. if (aIsLocal == 1 && g->CurrentFunc->mDefaultVarType == VAR_DECLARE_STATIC)
  7307. // v1.0.48: Lexikos: Current function is assume-static, so set static attribute.
  7308. // This will be overwritten (again) if this variable is being explicitly declared "local".
  7309. the_new_var->ConvertToStatic();
  7310. // If there's a lazy var list, aInsertPos provided by the caller is for it, so this new variable
  7311. // always gets inserted into that list because there's always room for one more (because the
  7312. // previously added variable would have purged it if it had reached capacity).
  7313. Var **lazy_var = aIsLocal ? g->CurrentFunc->mLazyVar : mLazyVar;
  7314. int &lazy_var_count = aIsLocal ? g->CurrentFunc->mLazyVarCount : mLazyVarCount; // Used further below too.
  7315. if (lazy_var)
  7316. {
  7317. if (aInsertPos != lazy_var_count) // Need to make room at the indicated position for this variable.
  7318. memmove(lazy_var + aInsertPos + 1, lazy_var + aInsertPos, (lazy_var_count - aInsertPos) * sizeof(Var *));
  7319. //else both are zero or the item is being inserted at the end of the list, so it's easy.
  7320. lazy_var[aInsertPos] = the_new_var;
  7321. ++lazy_var_count;
  7322. // In a testing creating between 200,000 and 400,000 variables, using a size of 1000 vs. 500 improves
  7323. // the speed by 17%, but when you substract out the binary search time (leaving only the insert time),
  7324. // the increase is more like 34%. But there is a diminishing return after that: Going to 2000 only
  7325. // gains 20%, and to 4000 only gains an addition 10%. Therefore, to conserve memory in functions that
  7326. // have so many variables that the lazy list is used, a good trade-off seems to be 2000 (8 KB of memory)
  7327. // per function that needs it.
  7328. #define MAX_LAZY_VARS 2000 // Don't make this larger than 90000 without altering the incremental increase of alloc_count further below.
  7329. if (lazy_var_count < MAX_LAZY_VARS) // The lazy list hasn't yet reached capacity, so no need to merge it into the main list.
  7330. return the_new_var;
  7331. }
  7332. // Since above didn't return, either there is no lazy list or the lazy list is full and needs to be
  7333. // merged into the main list.
  7334. // Create references to whichever variable list (local or global) is being acted upon. These
  7335. // references simplify the code:
  7336. Var **&var = aIsLocal ? g->CurrentFunc->mVar : mVar; // This needs to be a ref. too in case it needs to be realloc'd.
  7337. int &var_count = aIsLocal ? g->CurrentFunc->mVarCount : mVarCount;
  7338. int &var_count_max = aIsLocal ? g->CurrentFunc->mVarCountMax : mVarCountMax;
  7339. int alloc_count;
  7340. // Since the above would have returned if the lazy list is present but not yet full, if the left side
  7341. // of the OR below is false, it also means that lazy_var is NULL. Thus lazy_var==NULL is implicit for the
  7342. // right side of the OR:
  7343. if ((lazy_var && var_count + MAX_LAZY_VARS > var_count_max) || var_count == var_count_max)
  7344. {
  7345. // Increase by orders of magnitude each time because realloc() is probably an expensive operation
  7346. // in terms of hurting performance. So here, a little bit of memory is sacrificed to improve
  7347. // the expected level of performance for scripts that use hundreds of thousands of variables.
  7348. if (!var_count_max)
  7349. alloc_count = aIsLocal ? 100 : 1000; // 100 conserves memory since every function needs such a block, and most functions have much fewer than 100 local variables.
  7350. else if (var_count_max < 1000)
  7351. alloc_count = 1000;
  7352. else if (var_count_max < 9999) // Making this 9999 vs. 10000 allows an exact/whole number of lazy_var blocks to fit into main indices between 10000 and 99999
  7353. alloc_count = 9999;
  7354. else if (var_count_max < 100000)
  7355. {
  7356. alloc_count = 100000;
  7357. // This is also the threshold beyond which the lazy list is used to accelerate performance.
  7358. // Create the permanent lazy list:
  7359. Var **&lazy_var = aIsLocal ? g->CurrentFunc->mLazyVar : mLazyVar;
  7360. if ( !(lazy_var = (Var **)malloc(MAX_LAZY_VARS * sizeof(Var *))) )
  7361. {
  7362. ScriptError(ERR_OUTOFMEM);
  7363. return NULL;
  7364. }
  7365. }
  7366. else if (var_count_max < 1000000)
  7367. alloc_count = 1000000;
  7368. else
  7369. alloc_count = var_count_max + 1000000; // i.e. continue to increase by 4MB (1M*4) each time.
  7370. Var **temp = (Var **)realloc(var, alloc_count * sizeof(Var *)); // If passed NULL, realloc() will do a malloc().
  7371. if (!temp)
  7372. {
  7373. ScriptError(ERR_OUTOFMEM);
  7374. return NULL;
  7375. }
  7376. var = temp;
  7377. var_count_max = alloc_count;
  7378. }
  7379. if (!lazy_var)
  7380. {
  7381. if (aInsertPos != var_count) // Need to make room at the indicated position for this variable.
  7382. memmove(var + aInsertPos + 1, var + aInsertPos, (var_count - aInsertPos) * sizeof(Var *));
  7383. //else both are zero or the item is being inserted at the end of the list, so it's easy.
  7384. var[aInsertPos] = the_new_var;
  7385. ++var_count;
  7386. return the_new_var;
  7387. }
  7388. //else the variable was already inserted into the lazy list, so the above is not done.
  7389. // Since above didn't return, the lazy list is not only present, but full because otherwise it
  7390. // would have returned higher above.
  7391. // Since the lazy list is now at its max capacity, merge it into the main list (if the
  7392. // main list was at capacity, this section relies upon the fact that the above already
  7393. // increased its capacity by an amount far larger than the number of items containined
  7394. // in the lazy list).
  7395. // LAZY LIST: Although it's not nearly as good as hashing (which might be implemented in the future,
  7396. // though it would be no small undertaking since it affects so many design aspects, both load-time
  7397. // and runtime for scripts), this method of accelerating insertions into a binary search array is
  7398. // enormously beneficial because it improves the scalability of binary-search by two orders
  7399. // of magnitude (from about 100,000 variables to at least 5M). Credit for the idea goes to Lazlo.
  7400. // DETAILS:
  7401. // The fact that this merge operation is so much faster than total work required
  7402. // to insert each one into the main list is the whole reason for having the lazy
  7403. // list. In other words, the large memmove() that would otherwise be required
  7404. // to insert each new variable into the main list is completely avoided. Large memmove()s
  7405. // become dramatically more costly than small ones because apparently they can't fit into
  7406. // the CPU cache, so the operation would take hundreds or even thousands of times longer
  7407. // depending on the speed difference between main memory and CPU cache. But above and
  7408. // beyond the CPU cache issue, the lazy sorting method results in vastly less memory
  7409. // being moved than would have been required without it, so even if the CPU doesn't have
  7410. // a cache, the lazy list method vastly increases performance for scripts that have more
  7411. // than 100,000 variables, allowing at least 5 million variables to be created without a
  7412. // dramatic reduction in performance.
  7413. char *target_name;
  7414. Var **insert_pos, **insert_pos_prev;
  7415. int i, left, right, mid;
  7416. // Append any items from the lazy list to the main list that are alphabetically greater than
  7417. // the last item in the main list. Above has already ensured that the main list is large enough
  7418. // to accept all items in the lazy list.
  7419. for (i = lazy_var_count - 1, target_name = var[var_count - 1]->mName
  7420. ; i > -1 && stricmp(target_name, lazy_var[i]->mName) < 0
  7421. ; --i);
  7422. // Above is a self-contained loop.
  7423. // Now do a separate loop to append (in the *correct* order) anything found above.
  7424. for (int j = i + 1; j < lazy_var_count; ++j) // Might have zero iterations.
  7425. var[var_count++] = lazy_var[j];
  7426. lazy_var_count = i + 1; // The number of items that remain after moving out those that qualified.
  7427. // This will have zero iterations if the above already moved them all:
  7428. for (insert_pos = var + var_count, i = lazy_var_count - 1; i > -1; --i)
  7429. {
  7430. // Modified binary search that relies on the fact that caller has ensured a match will never
  7431. // be found in the main list for each item in the lazy list:
  7432. for (target_name = lazy_var[i]->mName, left = 0, right = (int)(insert_pos - var - 1); left <= right;)
  7433. {
  7434. mid = (left + right) / 2;
  7435. if (stricmp(target_name, var[mid]->mName) > 0) // lstrcmpi() is not used: 1) avoids breaking exisitng scripts; 2) provides consistent behavior across multiple locales; 3) performance.
  7436. left = mid + 1;
  7437. else // it must be < 0 because caller has ensured it can't be equal (i.e. that there will be no match)
  7438. right = mid - 1;
  7439. }
  7440. // Now "left" contains the insertion point is is known to be less than var_count due to a previous
  7441. // set of loops above. Make a gap there large enough to hold all items because that allows a
  7442. // smaller total amount of memory to be moved by shifting the gap to the left in the main list,
  7443. // gradually filling it as we go:
  7444. insert_pos_prev = insert_pos; // "prev" is the now the position of the beginning of the gap, but the gap is about to be shifted left by moving memory right.
  7445. insert_pos = var + left; // This is where it *would* be inserted if we weren't doing the accelerated merge.
  7446. memmove(insert_pos + i + 1, insert_pos, (insert_pos_prev - insert_pos) * sizeof(Var *));
  7447. var[left + i] = lazy_var[i]; // Now insert this item at the far right side of the gap just created.
  7448. }
  7449. var_count += lazy_var_count;
  7450. lazy_var_count = 0; // Indicate that the lazy var list is now empty.
  7451. return the_new_var;
  7452. }
  7453. void *Script::GetVarType(char *aVarName)
  7454. {
  7455. // Convert to lowercase to help performance a little (it typically only helps loadtime performance because
  7456. // this function is rarely called during script-runtime).
  7457. char lowercase[MAX_VAR_NAME_LENGTH + 1];
  7458. strlcpy(lowercase, aVarName, sizeof(lowercase)); // Caller should have ensured it fits, but call strlcpy() for maintainability.
  7459. CharLower(lowercase);
  7460. // Above: CharLower() is smaller in code size than strlwr(), but CharLower uses the OS locale and strlwr uses
  7461. // the setlocal() locale (which is always the same if setlocal() is never called). However, locale
  7462. // differences shouldn't affect the cases checked below; some evidence of this is at MSDN:
  7463. // "CharLower always maps uppercase I to lowercase I, even when the current language is Turkish or Azeri."
  7464. if (lowercase[0] != 'a' || lowercase[1] != '_') // This check helps average-case performance.
  7465. {
  7466. if ( !strcmp(lowercase, "true")
  7467. || !strcmp(lowercase, "false")) return BIV_True_False;
  7468. if (!strcmp(lowercase, "clipboard")) return (void *)VAR_CLIPBOARD;
  7469. if (!strcmp(lowercase, "clipboardall")) return (void *)VAR_CLIPBOARDALL;
  7470. if (!strcmp(lowercase, "comspec")) return BIV_ComSpec; // Lacks an "A_" prefix for backward compatibility with pre-NoEnv scripts and also it's easier to type & remember.
  7471. if (!strcmp(lowercase, "programfiles")) return BIV_ProgramFiles; // v1.0.43.08: Added to ease the transition to #NoEnv.
  7472. // Otherwise:
  7473. return (void *)VAR_NORMAL;
  7474. }
  7475. // Otherwise, lowercase begins with "a_", so it's probably one of the built-in variables.
  7476. char *lower = lowercase + 2;
  7477. // Keeping the most common ones near the top helps performance a little.
  7478. if (!strcmp(lower, "index")) return BIV_LoopIndex; // A short name since it's typed so often.
  7479. if ( !strcmp(lower, "mmmm") // Long name of month.
  7480. || !strcmp(lower, "mmm") // 3-char abbrev. month name.
  7481. || !strcmp(lower, "dddd") // Name of weekday, e.g. Sunday
  7482. || !strcmp(lower, "ddd") ) // Abbrev., e.g. Sun
  7483. return BIV_MMM_DDD;
  7484. if ( !strcmp(lower, "yyyy")
  7485. || !strcmp(lower, "year") // Same as above.
  7486. || !strcmp(lower, "mm") // 01 thru 12
  7487. || !strcmp(lower, "mon") // Same
  7488. || !strcmp(lower, "dd") // 01 thru 31
  7489. || !strcmp(lower, "mday") // Same
  7490. || !strcmp(lower, "wday")
  7491. || !strcmp(lower, "yday")
  7492. || !strcmp(lower, "yweek")
  7493. || !strcmp(lower, "hour")
  7494. || !strcmp(lower, "min")
  7495. || !strcmp(lower, "sec")
  7496. || !strcmp(lower, "msec") )
  7497. return BIV_DateTime;
  7498. if (!strcmp(lower, "tickcount")) return BIV_TickCount;
  7499. if ( !strcmp(lower, "now")
  7500. || !strcmp(lower, "nowutc")) return BIV_Now;
  7501. if (!strcmp(lower, "workingdir")) return BIV_WorkingDir;
  7502. if (!strcmp(lower, "scriptname")) return BIV_ScriptName;
  7503. if (!strcmp(lower, "scriptdir")) return BIV_ScriptDir;
  7504. if (!strcmp(lower, "scriptfullpath")) return BIV_ScriptFullPath;
  7505. if (!strcmp(lower, "linenumber")) return BIV_LineNumber;
  7506. if (!strcmp(lower, "linefile")) return BIV_LineFile;
  7507. // A_IsCompiled is left blank/undefined in uncompiled scripts.
  7508. #ifdef AUTOHOTKEYSC
  7509. if (!strcmp(lower, "iscompiled")) return BIV_IsCompiled;
  7510. #endif
  7511. if ( !strcmp(lower, "batchlines")
  7512. || !strcmp(lower, "numbatchlines")) return BIV_BatchLines;
  7513. if (!strcmp(lower, "titlematchmode")) return BIV_TitleMatchMode;
  7514. if (!strcmp(lower, "titlematchmodespeed")) return BIV_TitleMatchModeSpeed;
  7515. if (!strcmp(lower, "detecthiddenwindows")) return BIV_DetectHiddenWindows;
  7516. if (!strcmp(lower, "detecthiddentext")) return BIV_DetectHiddenText;
  7517. if (!strcmp(lower, "autotrim")) return BIV_AutoTrim;
  7518. if (!strcmp(lower, "stringcasesense")) return BIV_StringCaseSense;
  7519. if (!strcmp(lower, "formatinteger")) return BIV_FormatInteger;
  7520. if (!strcmp(lower, "formatfloat")) return BIV_FormatFloat;
  7521. if (!strcmp(lower, "keydelay")) return BIV_KeyDelay;
  7522. if (!strcmp(lower, "windelay")) return BIV_WinDelay;
  7523. if (!strcmp(lower, "controldelay")) return BIV_ControlDelay;
  7524. if (!strcmp(lower, "mousedelay")) return BIV_MouseDelay;
  7525. if (!strcmp(lower, "defaultmousespeed")) return BIV_DefaultMouseSpeed;
  7526. if (!strcmp(lower, "ispaused")) return BIV_IsPaused;
  7527. if (!strcmp(lower, "iscritical")) return BIV_IsCritical;
  7528. if (!strcmp(lower, "issuspended")) return BIV_IsSuspended;
  7529. if (!strcmp(lower, "iconhidden")) return BIV_IconHidden;
  7530. if (!strcmp(lower, "icontip")) return BIV_IconTip;
  7531. if (!strcmp(lower, "iconfile")) return BIV_IconFile;
  7532. if (!strcmp(lower, "iconnumber")) return BIV_IconNumber;
  7533. if (!strcmp(lower, "exitreason")) return BIV_ExitReason;
  7534. if (!strcmp(lower, "ostype")) return BIV_OSType;
  7535. if (!strcmp(lower, "osversion")) return BIV_OSVersion;
  7536. if (!strcmp(lower, "language")) return BIV_Language;
  7537. if ( !strcmp(lower, "computername")
  7538. || !strcmp(lower, "username")) return BIV_UserName_ComputerName;
  7539. if (!strcmp(lower, "windir")) return BIV_WinDir;
  7540. if (!strcmp(lower, "temp")) return BIV_Temp; // Debatably should be A_TempDir, but brevity seemed more popular with users, perhaps for heavy uses of the temp folder.
  7541. if (!strcmp(lower, "programfiles")) return BIV_ProgramFiles;
  7542. if (!strcmp(lower, "mydocuments")) return BIV_MyDocuments;
  7543. if ( !strcmp(lower, "appdata")
  7544. || !strcmp(lower, "appdatacommon")) return BIV_AppData;
  7545. if ( !strcmp(lower, "desktop")
  7546. || !strcmp(lower, "desktopcommon")) return BIV_Desktop;
  7547. if ( !strcmp(lower, "startmenu")
  7548. || !strcmp(lower, "startmenucommon")) return BIV_StartMenu;
  7549. if ( !strcmp(lower, "programs")
  7550. || !strcmp(lower, "programscommon")) return BIV_Programs;
  7551. if ( !strcmp(lower, "startup")
  7552. || !strcmp(lower, "startupcommon")) return BIV_Startup;
  7553. if (!strcmp(lower, "isadmin")) return BIV_IsAdmin;
  7554. if (!strcmp(lower, "cursor")) return BIV_Cursor;
  7555. if ( !strcmp(lower, "caretx")
  7556. || !strcmp(lower, "carety")) return BIV_Caret;
  7557. if ( !strcmp(lower, "screenwidth")
  7558. || !strcmp(lower, "screenheight")) return BIV_ScreenWidth_Height;
  7559. if (!strncmp(lower, "ipaddress", 9))
  7560. {
  7561. lower += 9;
  7562. return (*lower >= '1' && *lower <= '4'
  7563. && !lower[1]) // Make sure has only one more character rather than none or several (e.g. A_IPAddress1abc should not be match).
  7564. ? BIV_IPAddress
  7565. : (void *)VAR_NORMAL; // Otherwise it can't be a match for any built-in variable.
  7566. }
  7567. if (!strncmp(lower, "loop", 4))
  7568. {
  7569. lower += 4;
  7570. if (!strcmp(lower, "readline")) return BIV_LoopReadLine;
  7571. if (!strcmp(lower, "field")) return BIV_LoopField;
  7572. if (!strncmp(lower, "file", 4))
  7573. {
  7574. lower += 4;
  7575. if (!strcmp(lower, "name")) return BIV_LoopFileName;
  7576. if (!strcmp(lower, "shortname")) return BIV_LoopFileShortName;
  7577. if (!strcmp(lower, "ext")) return BIV_LoopFileExt;
  7578. if (!strcmp(lower, "dir")) return BIV_LoopFileDir;
  7579. if (!strcmp(lower, "fullpath")) return BIV_LoopFileFullPath;
  7580. if (!strcmp(lower, "longpath")) return BIV_LoopFileLongPath;
  7581. if (!strcmp(lower, "shortpath")) return BIV_LoopFileShortPath;
  7582. if (!strcmp(lower, "attrib")) return BIV_LoopFileAttrib;
  7583. if ( !strcmp(lower, "timemodified")
  7584. || !strcmp(lower, "timecreated")
  7585. || !strcmp(lower, "timeaccessed")) return BIV_LoopFileTime;
  7586. if ( !strcmp(lower, "size")
  7587. || !strcmp(lower, "sizekb")
  7588. || !strcmp(lower, "sizemb")) return BIV_LoopFileSize;
  7589. // Otherwise, it can't be a match for any built-in variable:
  7590. return (void *)VAR_NORMAL;
  7591. }
  7592. if (!strncmp(lower, "reg", 3))
  7593. {
  7594. lower += 3;
  7595. if (!strcmp(lower, "type")) return BIV_LoopRegType;
  7596. if (!strcmp(lower, "key")) return BIV_LoopRegKey;
  7597. if (!strcmp(lower, "subkey")) return BIV_LoopRegSubKey;
  7598. if (!strcmp(lower, "name")) return BIV_LoopRegName;
  7599. if (!strcmp(lower, "timemodified")) return BIV_LoopRegTimeModified;
  7600. // Otherwise, it can't be a match for any built-in variable:
  7601. return (void *)VAR_NORMAL;
  7602. }
  7603. }
  7604. if (!strcmp(lower, "thisfunc")) return BIV_ThisFunc;
  7605. if (!strcmp(lower, "thislabel")) return BIV_ThisLabel;
  7606. if (!strcmp(lower, "thismenuitem")) return BIV_ThisMenuItem;
  7607. if (!strcmp(lower, "thismenuitempos")) return BIV_ThisMenuItemPos;
  7608. if (!strcmp(lower, "thismenu")) return BIV_ThisMenu;
  7609. if (!strcmp(lower, "thishotkey")) return BIV_ThisHotkey;
  7610. if (!strcmp(lower, "priorhotkey")) return BIV_PriorHotkey;
  7611. if (!strcmp(lower, "timesincethishotkey")) return BIV_TimeSinceThisHotkey;
  7612. if (!strcmp(lower, "timesincepriorhotkey")) return BIV_TimeSincePriorHotkey;
  7613. if (!strcmp(lower, "endchar")) return BIV_EndChar;
  7614. if (!strcmp(lower, "lasterror")) return BIV_LastError;
  7615. if (!strcmp(lower, "eventinfo")) return BIV_EventInfo; // It's called "EventInfo" vs. "GuiEventInfo" because it applies to non-Gui events such as OnClipboardChange.
  7616. if (!strcmp(lower, "guicontrol")) return BIV_GuiControl;
  7617. if ( !strcmp(lower, "guicontrolevent") // v1.0.36: A_GuiEvent was added as a synonym for A_GuiControlEvent because it seems unlikely that A_GuiEvent will ever be needed for anything:
  7618. || !strcmp(lower, "guievent")) return BIV_GuiEvent;
  7619. if ( !strcmp(lower, "gui")
  7620. || !strcmp(lower, "guiwidth")
  7621. || !strcmp(lower, "guiheight")
  7622. || !strcmp(lower, "guix") // Naming: Brevity seems more a benefit than would A_GuiEventX's improved clarity.
  7623. || !strcmp(lower, "guiy")) return BIV_Gui; // These can be overloaded if a GuiMove label or similar is ever needed.
  7624. if (!strcmp(lower, "timeidle")) return BIV_TimeIdle;
  7625. if (!strcmp(lower, "timeidlephysical")) return BIV_TimeIdlePhysical;
  7626. if ( !strcmp(lower, "space")
  7627. || !strcmp(lower, "tab")) return BIV_Space_Tab;
  7628. if (!strcmp(lower, "ahkversion")) return BIV_AhkVersion;
  7629. if (!strcmp(lower, "ahkpath")) return BIV_AhkPath;
  7630. // Since above didn't return:
  7631. return (void *)VAR_NORMAL;
  7632. }
  7633. WinGroup *Script::FindGroup(char *aGroupName, bool aCreateIfNotFound)
  7634. // Caller must ensure that aGroupName isn't NULL. But if it's the empty string, NULL is returned.
  7635. // Returns the Group whose name matches aGroupName. If it doesn't exist, it is created if aCreateIfNotFound==true.
  7636. // Thread-safety: This function is thread-safe (except when when called with aCreateIfNotFound==true) even when
  7637. // the main thread happens to be calling AddGroup() and changing the linked list while it's being traversed here
  7638. // by the hook thread. However, any subsequent changes to this function or AddGroup() must be carefully reviewed.
  7639. {
  7640. if (!*aGroupName)
  7641. return NULL;
  7642. for (WinGroup *group = mFirstGroup; group != NULL; group = group->mNextGroup)
  7643. if (!stricmp(group->mName, aGroupName)) // lstrcmpi() is not used: 1) avoids breaking exisitng scripts; 2) provides consistent behavior across multiple locales; 3) performance.
  7644. return group; // Match found.
  7645. // Otherwise, no match found, so create a new group.
  7646. if (!aCreateIfNotFound || AddGroup(aGroupName) != OK)
  7647. return NULL;
  7648. return mLastGroup;
  7649. }
  7650. ResultType Script::AddGroup(char *aGroupName)
  7651. // Returns OK or FAIL.
  7652. // The caller must already have verfied that this isn't a duplicate group.
  7653. // This function is not thread-safe because it adds an entry to the quasi-global list of window groups.
  7654. // In addition, if this function is being called by one thread while another thread is calling FindGroup(),
  7655. // the thread-safety notes in FindGroup() apply.
  7656. {
  7657. size_t aGroupName_length = strlen(aGroupName);
  7658. if (aGroupName_length > MAX_VAR_NAME_LENGTH)
  7659. return ScriptError("Group name too long.", aGroupName);
  7660. if (!Var::ValidateName(aGroupName, false, DISPLAY_NO_ERROR)) // Seems best to use same validation as var names.
  7661. return ScriptError("Illegal group name.", aGroupName);
  7662. char *new_name = SimpleHeap::Malloc(aGroupName, aGroupName_length);
  7663. if (!new_name)
  7664. return FAIL; // It already displayed the error for us.
  7665. // The precise method by which the follows steps are done should be thread-safe even if
  7666. // some other thread calls FindGroup() in the middle of the operation. But any changes
  7667. // must be carefully reviewed:
  7668. WinGroup *the_new_group = new WinGroup(new_name);
  7669. if (the_new_group == NULL)
  7670. return ScriptError(ERR_OUTOFMEM);
  7671. if (mFirstGroup == NULL)
  7672. mFirstGroup = the_new_group;
  7673. else
  7674. mLastGroup->mNextGroup = the_new_group;
  7675. // This must be done after the above:
  7676. mLastGroup = the_new_group;
  7677. return OK;
  7678. }
  7679. Line *Script::PreparseBlocks(Line *aStartingLine, bool aFindBlockEnd, Line *aParentLine)
  7680. // aFindBlockEnd should be true, only when this function is called
  7681. // by itself. The end of this function relies upon this definition.
  7682. // Will return NULL to the top-level caller if there's an error, or if
  7683. // mLastLine is NULL (i.e. the script is empty).
  7684. {
  7685. // Not thread-safe, so this can only parse one script at a time.
  7686. // Not a problem for the foreseeable future:
  7687. static int nest_level; // Level zero is the outermost one: outside all blocks.
  7688. static bool abort;
  7689. if (!aParentLine)
  7690. {
  7691. // We were called from outside, not recursively, so init these. This is
  7692. // very important if this function is ever to be called from outside
  7693. // more than once, even though it isn't currently:
  7694. nest_level = 0;
  7695. abort = false;
  7696. }
  7697. int i, open_parens;
  7698. bool in_quotes;
  7699. DerefType *deref, *deref2;
  7700. char *param_start, *param_end, *param_last_char, *cp, c;
  7701. bool found;
  7702. // Don't check aStartingLine here at top: only do it at the bottom
  7703. // for its differing return values.
  7704. for (Line *line = aStartingLine; line;)
  7705. {
  7706. // Check if any of each arg's derefs are function calls. If so, do some validation and
  7707. // preprocessing to set things up for better runtime performance:
  7708. for (i = 0; i < line->mArgc; ++i) // For each arg.
  7709. {
  7710. ArgStruct &this_arg = line->mArg[i]; // For performance and convenience.
  7711. // Exclude the derefs of output and input vars from consideration, since they can't
  7712. // be function calls:
  7713. if (!this_arg.is_expression) // For now, only expressions are capable of calling functions. If ever change this, might want to add a check here for this_arg.type != ARG_TYPE_NORMAL (for performance).
  7714. continue;
  7715. if (this_arg.deref) // No function-calls are present because the expression contains neither variables nor function calls.
  7716. {
  7717. for (deref = this_arg.deref; deref->marker; ++deref) // For each deref.
  7718. {
  7719. if (!deref->is_function)
  7720. continue;
  7721. if ( !(deref->func = FindFunc(deref->marker, deref->length)) )
  7722. {
  7723. #ifndef AUTOHOTKEYSC
  7724. bool error_was_shown;
  7725. if ( !(deref->func = FindFuncInLibrary(deref->marker, deref->length, error_was_shown)) )
  7726. {
  7727. abort = true; // So that the caller doesn't also report an error.
  7728. // When above already displayed the proximate cause of the error, it's usually
  7729. // undesirable to show the cascade effects of that error in a second dialog:
  7730. return error_was_shown ? NULL : line->PreparseError(ERR_NONEXISTENT_FUNCTION, deref->marker);
  7731. }
  7732. #else
  7733. abort = true;
  7734. return line->PreparseError(ERR_NONEXISTENT_FUNCTION, deref->marker);
  7735. #endif
  7736. }
  7737. // An earlier stage has ensured that if the function exists, it's mJumpToLine is non-NULL.
  7738. Func &func = *deref->func; // For performance and convenience.
  7739. // Ealier stage has ensured that strchr() will always find an open-parenthesis:
  7740. for (deref->param_count = 0, param_start = omit_leading_whitespace(strchr(deref->marker, '(') + 1);;)
  7741. {
  7742. // For each parameter of this function-call.
  7743. if (*param_start == ')') // No more params.
  7744. break;
  7745. if (*param_start == ',')
  7746. {
  7747. abort = true; // So that the caller doesn't also report an error.
  7748. return line->PreparseError(ERR_BLANK_PARAM, deref->marker);
  7749. }
  7750. // Although problems such as blank/empty parameters and missing close-paren were already
  7751. // checked by DefineFunc(), that was done only for the function's formal definition, not
  7752. // the calls to it. And although parentheses were balanced in all expressions at an earlier
  7753. // stage, it's done again here in case function calls are ever allowed to be occur in
  7754. // a non-expression (or dynamic functions calls such as FnArray%i%() are ever supported):
  7755. if (!*param_start)
  7756. {
  7757. abort = true; // So that the caller doesn't also report an error.
  7758. return line->PreparseError(ERR_MISSING_CLOSE_PAREN, deref->marker);
  7759. }
  7760. // Find the end of this function-param by taking into account nested parentheses, omitting
  7761. // from consideration any parentheses inside of quoted/literal strings. When this loop is done,
  7762. // param_end this param's final comma or this function-call's close-paren when this param
  7763. // is the last one.
  7764. for (in_quotes = false, open_parens = 0, param_end = param_start;; ++param_end)
  7765. {
  7766. // If nested function calls are encountered within the function call being examined
  7767. // now, they are skipped over because they will be processed here only when the outer
  7768. // loop gets to them.
  7769. c = *param_end; // switch() is not used so that "break" can be used to exit the loop.
  7770. if (c == ',')
  7771. {
  7772. if (!(in_quotes || open_parens)) // This comma belongs to our function, so it marks the end of this param.
  7773. break;
  7774. //else it's not a real comma since it's inside the parentheses of a subexpression or
  7775. // sub-function, or inside a quoted/literal string. Ignore it.
  7776. }
  7777. else if (c == ')')
  7778. {
  7779. if (!in_quotes)
  7780. {
  7781. if (!open_parens) // This is our function's close-paren, and thus the end of this param.
  7782. break;
  7783. else
  7784. --open_parens;
  7785. }
  7786. //else it's not a real paren since it's inside a quoted/literal string. Ignore it.
  7787. }
  7788. else if (c == '(')
  7789. {
  7790. if (!in_quotes) // Literal parentheses inside a quoted string should not be counted for this purpose.
  7791. ++open_parens;
  7792. }
  7793. else if (c == '"')
  7794. // The simple method below is sufficient for our purpose even if a quoted string contains
  7795. // pairs of double-quotes to represent a single literal quote, e.g. "quoted ""word""".
  7796. // In other words, it relies on the fact that there must be an even number of quotes
  7797. // inside any mandatory-numeric arg that is an expression such as x=="red,blue"
  7798. in_quotes = !in_quotes;
  7799. else if (!c) // This function lacks a closing paren.
  7800. {
  7801. // Might happen if this is a syntax error not catchable by the earlier stage of syntax
  7802. // checking (paren balancing, quote balancing, etc.)
  7803. abort = true; // So that the caller doesn't also report an error.
  7804. return line->PreparseError(ERR_MISSING_CLOSE_PAREN, deref->marker);
  7805. }
  7806. //else it's some other, non-special character, so ignore it.
  7807. } // for() that finds the end of this param of this function.
  7808. // Above would have returned unless *param_end is either a comma or close-paren (namely the
  7809. // one that terminates this parameter of this function).
  7810. if (deref->param_count >= func.mParamCount) // Check this every iteration to avoid going beyond MAX_FUNCTION_PARAMS.
  7811. {
  7812. abort = true; // So that the caller doesn't also report an error.
  7813. return line->PreparseError("Too many parameters passed to function.", deref->marker);
  7814. }
  7815. // Below relies on the above check having been done first to avoid reading beyond the
  7816. // end of the mParam array.
  7817. // If this parameter is formally declared as ByRef, report a load-time error if
  7818. // the actual-parameter is obviously not a variable (can't catch everything, such
  7819. // as invalid double derefs, e.g. Array%VarContainingSpaces%):
  7820. if (!func.mIsBuiltIn && func.mParam[deref->param_count].is_byref)
  7821. {
  7822. // First check if there are any EXPR_TELLTALES characters in this param, since the
  7823. // presence of an expression for this parameter means it can't resolve to a variable
  7824. // as required by ByRef:
  7825. for (cp = param_start, param_last_char = omit_trailing_whitespace(param_start, param_end - 1)
  7826. ; cp <= param_last_char; ++cp)
  7827. {
  7828. if (*cp == ':' && cp[1] == '=')
  7829. // v1.0.46.05: This section fixes the inability to pass ByRef certain non-trivial
  7830. // assignments like X := " ". Although this doesn't give 100% detection, something
  7831. // more elaborate seems unjustified (in both code size and performance) given that
  7832. // this is only a syntax check.
  7833. break;
  7834. if (strchr(EXPR_FORBIDDEN_BYREF, *cp)) // This character isn't allowed in something passed ByRef unless it's an assignment (which is checked below).
  7835. {
  7836. if (Line::StartsWithAssignmentOp(cp) || strstr(cp, " ? ")) // v1.0.46.09: Also allow a ternary unconditionally, because it can be an arbitrarily complex expression followed by two branches that yield variables.
  7837. {
  7838. // Skip over :=, +=, -=, *=, /=, ++, -- ... because they can be passed ByRef.
  7839. // In fact, don't even continue the loop because any assignment can be followed
  7840. // by an arbitrarily complex sub-expression that shouldn't disqualify ByRef.
  7841. break;
  7842. }
  7843. abort = true; // So that the caller doesn't also report an error.
  7844. return line->PreparseError(ERR_BYREF, param_start); // param_start seems more informative than func.mParam[deref->param_count].var->mName
  7845. }
  7846. }
  7847. // Below relies on the above having been done because the above should prevent
  7848. // any is_function derefs from being possible since their parentheses would have been caught
  7849. // as an error:
  7850. // For each deref after the function name itself, ensure that there is at least
  7851. // one deref in between this param's param_start and param_end. This finds many
  7852. // common syntax errors such as passing a literal number or string to a ByRef
  7853. // parameter. Note that there can be more than one for something like Array%i%_%j%
  7854. // or a ternary like true ? x : y.
  7855. for (found = false, deref2 = deref + 1; deref2->marker; ++deref2)
  7856. if (deref2->marker >= param_start && deref2->marker < param_end)
  7857. {
  7858. found = true;
  7859. break;
  7860. }
  7861. if (!found)
  7862. {
  7863. abort = true; // So that the caller doesn't also report an error.
  7864. return line->PreparseError(ERR_BYREF, param_start); // param_start seems more informative than func.mParam[deref->param_count].var->mName
  7865. }
  7866. }
  7867. ++deref->param_count;
  7868. // Set up for the next iteration:
  7869. param_start = param_end; // Must already be a comma or close-paren due to checking higher above.
  7870. if (*param_start == ',')
  7871. {
  7872. param_start = omit_leading_whitespace(param_start + 1);
  7873. if (*param_start == ')')
  7874. {
  7875. abort = true; // So that the caller doesn't also report an error.
  7876. return line->PreparseError(ERR_BLANK_PARAM, param_start); // Report param_start vs. aBuf to give an idea of where the blank parameter is in a possibly long list of params.
  7877. }
  7878. }
  7879. //else it might be ')', in which case the next iteration will handle it.
  7880. // Above has ensured that param_start now points to the next parameter, or ')' if none.
  7881. } // for each parameter of this function call.
  7882. if (deref->param_count < func.mMinParams)
  7883. {
  7884. abort = true; // So that the caller doesn't also report an error.
  7885. return line->PreparseError("Too few parameters passed to function.", deref->marker);
  7886. }
  7887. } // for each deref of this arg
  7888. } // if (this_arg.deref)
  7889. if (!line->ExpressionToPostfix(this_arg)) // At this stage, this_arg.is_expression is known to be true. Doing this here, after the script has been loaded, might improve the compactness/adjacent-ness of the compiled expressions in memory, which might improve performance due to CPU caching.
  7890. {
  7891. abort = true; // So that the caller doesn't also report an error.
  7892. return NULL; // The function above already displayed the error msg.
  7893. }
  7894. } // for each arg of this line
  7895. // All lines in our recursion layer are assigned to the block that the caller specified:
  7896. if (line->mParentLine == NULL) // i.e. don't do it if it's already "owned" by an IF or ELSE.
  7897. line->mParentLine = aParentLine; // Can be NULL.
  7898. if (ACT_IS_IF_OR_ELSE_OR_LOOP(line->mActionType) || line->mActionType == ACT_REPEAT)
  7899. {
  7900. // In this case, the loader should have already ensured that line->mNextLine is not NULL.
  7901. if (line->mNextLine->mActionType == ACT_BLOCK_BEGIN && line->mNextLine->mAttribute == ATTR_TRUE)
  7902. {
  7903. abort = true; // So that the caller doesn't also report an error.
  7904. return line->PreparseError("Improper line below this."); // Short message since so rare. A function must not be defined directly below an IF/ELSE/LOOP because runtime evaluation won't handle it properly.
  7905. }
  7906. // Make the line immediately following each ELSE, IF or LOOP be enclosed by that stmt.
  7907. // This is done to make it illegal for a Goto or Gosub to jump into a deeper layer,
  7908. // such as in this example:
  7909. // #y::
  7910. // ifwinexist, pad
  7911. // {
  7912. // goto, label1
  7913. // ifwinexist, pad
  7914. // label1:
  7915. // ; With or without the enclosing block, the goto would still go to an illegal place
  7916. // ; in the below, resulting in an "unexpected else" error:
  7917. // {
  7918. // msgbox, ifaction
  7919. // } ; not necessary to make this line enclosed by the if because labels can't point to it?
  7920. // else
  7921. // msgbox, elseaction
  7922. // }
  7923. // return
  7924. line->mNextLine->mParentLine = line;
  7925. // Go onto the IF's or ELSE's action in case it too is an IF, rather than skipping over it:
  7926. line = line->mNextLine;
  7927. continue;
  7928. }
  7929. switch (line->mActionType)
  7930. {
  7931. case ACT_BLOCK_BEGIN:
  7932. // Some insane limit too large to ever likely be exceeded, yet small enough not
  7933. // to be a risk of stack overflow when recursing in ExecUntil(). Mostly, this is
  7934. // here to reduce the chance of a program crash if a binary file, a corrupted file,
  7935. // or something unexpected has been loaded as a script when it shouldn't have been.
  7936. // Update: Increased the limit from 100 to 1000 so that large "else if" ladders
  7937. // can be constructed. Going much larger than 1000 seems unwise since ExecUntil()
  7938. // will have to recurse for each nest-level, possibly resulting in stack overflow
  7939. // if things get too deep:
  7940. if (nest_level > 1000)
  7941. {
  7942. abort = true; // So that the caller doesn't also report an error.
  7943. return line->PreparseError("Nesting too deep."); // Short msg since so rare.
  7944. }
  7945. // Since the current convention is to store the line *after* the
  7946. // BLOCK_END as the BLOCK_BEGIN's related line, that line can
  7947. // be legitimately NULL if this block's BLOCK_END is the last
  7948. // line in the script. So it's up to the called function
  7949. // to report an error if it never finds a BLOCK_END for us.
  7950. // UPDATE: The design requires that we do it here instead:
  7951. ++nest_level;
  7952. if (NULL == (line->mRelatedLine = PreparseBlocks(line->mNextLine, 1, line)))
  7953. if (abort) // the above call already reported the error.
  7954. return NULL;
  7955. else
  7956. {
  7957. abort = true; // So that the caller doesn't also report an error.
  7958. return line->PreparseError(ERR_MISSING_CLOSE_BRACE);
  7959. }
  7960. --nest_level;
  7961. // The convention is to have the BLOCK_BEGIN's related_line
  7962. // point to the line *after* the BLOCK_END.
  7963. line->mRelatedLine = line->mRelatedLine->mNextLine; // Might be NULL now.
  7964. // Otherwise, since any blocks contained inside this one would already
  7965. // have been handled by the recursion in the above call, continue searching
  7966. // from the end of this block:
  7967. line = line->mRelatedLine; // If NULL, the loop-condition will catch it.
  7968. break;
  7969. case ACT_BLOCK_END:
  7970. // Return NULL (failure) if the end was found but we weren't looking for one
  7971. // (i.e. it's an orphan). Otherwise return the line after the block_end line,
  7972. // which will become the caller's mRelatedLine. UPDATE: Return the
  7973. // END_BLOCK line itself so that the caller can differentiate between
  7974. // a NULL due to end-of-script and a NULL caused by an error:
  7975. return aFindBlockEnd ? line // Doesn't seem necessary to set abort to true.
  7976. : line->PreparseError(ERR_MISSING_OPEN_BRACE);
  7977. default: // Continue line-by-line.
  7978. line = line->mNextLine;
  7979. } // switch()
  7980. } // for each line
  7981. // End of script has been reached. <line> is now NULL so don't attempt to dereference it.
  7982. // If we were still looking for an EndBlock to match up with a begin, that's an error.
  7983. // Don't report the error here because we don't know which begin-block is waiting
  7984. // for an end (the caller knows and must report the error). UPDATE: Must report
  7985. // the error here (see comments further above for explanation). UPDATE #2: Changed
  7986. // it again: Now we let the caller handle it again:
  7987. if (aFindBlockEnd)
  7988. //return mLastLine->PreparseError("The script ends while a block is still open (missing }).");
  7989. return NULL;
  7990. // If no error, return something non-NULL to indicate success to the top-level caller.
  7991. // We know we're returning to the top-level caller because aFindBlockEnd is only true
  7992. // when we're recursed, and in that case the above would have returned. Thus,
  7993. // we're not recursed upon reaching this line:
  7994. return mLastLine;
  7995. }
  7996. Line *Script::PreparseIfElse(Line *aStartingLine, ExecUntilMode aMode, AttributeType aLoopTypeFile
  7997. , AttributeType aLoopTypeReg, AttributeType aLoopTypeRead, AttributeType aLoopTypeParse)
  7998. // Zero is the default for aMode, otherwise:
  7999. // Will return NULL to the top-level caller if there's an error, or if
  8000. // mLastLine is NULL (i.e. the script is empty).
  8001. // Note: This function should be called with aMode == ONLY_ONE_LINE
  8002. // only when aStartingLine's ActionType is something recursable such
  8003. // as IF and BEGIN_BLOCK. Otherwise, it won't return after only one line.
  8004. {
  8005. static BOOL sInFunctionBody = FALSE; // Improves loadtime performance by allowing IsOutsideAnyFunctionBody() to be called only when necessary.
  8006. // Don't check aStartingLine here at top: only do it at the bottom
  8007. // for it's differing return values.
  8008. Line *line_temp;
  8009. // Although rare, a statement can be enclosed in more than one type of special loop,
  8010. // e.g. both a file-loop and a reg-loop:
  8011. AttributeType loop_type_file, loop_type_reg, loop_type_read, loop_type_parse;
  8012. for (Line *line = aStartingLine; line != NULL;)
  8013. {
  8014. if ( ACT_IS_IF(line->mActionType)
  8015. || line->mActionType == ACT_LOOP
  8016. || line->mActionType == ACT_WHILE // Lexikos: Added check for ACT_WHILE.
  8017. || line->mActionType == ACT_REPEAT )
  8018. {
  8019. // ActionType is an IF or a LOOP.
  8020. line_temp = line->mNextLine; // line_temp is now this IF's or LOOP's action-line.
  8021. // Update: Below is commented out because it's now impossible (since all scripts end in ACT_EXIT):
  8022. //if (line_temp == NULL) // This is an orphan IF/LOOP (has no action-line) at the end of the script.
  8023. // return line->PreparseError("Q"); // Placeholder. Formerly "This if-statement or loop has no action."
  8024. // Other things rely on this check having been done, such as "if (line->mRelatedLine != NULL)":
  8025. if (line_temp->mActionType == ACT_ELSE || line_temp->mActionType == ACT_BLOCK_END)
  8026. return line->PreparseError("Inappropriate line beneath IF or LOOP.");
  8027. // We're checking for ATTR_LOOP_FILEPATTERN here to detect whether qualified commands enclosed
  8028. // in a true file loop are allowed to omit their filename parameter:
  8029. loop_type_file = ATTR_NONE;
  8030. if (aLoopTypeFile == ATTR_LOOP_FILEPATTERN || line->mAttribute == ATTR_LOOP_FILEPATTERN)
  8031. // i.e. if either one is a file-loop, that's enough to establish
  8032. // the fact that we're in a file loop.
  8033. loop_type_file = ATTR_LOOP_FILEPATTERN;
  8034. else if (aLoopTypeFile == ATTR_LOOP_UNKNOWN || line->mAttribute == ATTR_LOOP_UNKNOWN)
  8035. // ATTR_LOOP_UNKNOWN takes precedence over ATTR_LOOP_NORMAL because
  8036. // we can't be sure if we're in a file loop, but it's correct to
  8037. // assume that we are (otherwise, unwarranted syntax errors may be reported
  8038. // later on in here).
  8039. loop_type_file = ATTR_LOOP_UNKNOWN;
  8040. else if (aLoopTypeFile == ATTR_LOOP_NORMAL || line->mAttribute == ATTR_LOOP_NORMAL)
  8041. loop_type_file = ATTR_LOOP_NORMAL;
  8042. else if (aLoopTypeFile == ATTR_LOOP_WHILE || line->mAttribute == ATTR_LOOP_WHILE) // Lexikos: ACT_WHILE
  8043. loop_type_file = ATTR_LOOP_WHILE;
  8044. // The section is the same as above except for registry vs. file loops:
  8045. loop_type_reg = ATTR_NONE;
  8046. if (aLoopTypeReg == ATTR_LOOP_REG || line->mAttribute == ATTR_LOOP_REG)
  8047. loop_type_reg = ATTR_LOOP_REG;
  8048. else if (aLoopTypeReg == ATTR_LOOP_UNKNOWN || line->mAttribute == ATTR_LOOP_UNKNOWN)
  8049. loop_type_reg = ATTR_LOOP_UNKNOWN;
  8050. else if (aLoopTypeReg == ATTR_LOOP_NORMAL || line->mAttribute == ATTR_LOOP_NORMAL)
  8051. loop_type_reg = ATTR_LOOP_NORMAL;
  8052. else if (aLoopTypeReg == ATTR_LOOP_WHILE || line->mAttribute == ATTR_LOOP_WHILE) // Lexikos: ACT_WHILE
  8053. loop_type_reg = ATTR_LOOP_WHILE;
  8054. // Same as above except for READ-FILE loops:
  8055. loop_type_read = ATTR_NONE;
  8056. if (aLoopTypeRead == ATTR_LOOP_READ_FILE || line->mAttribute == ATTR_LOOP_READ_FILE)
  8057. loop_type_read = ATTR_LOOP_READ_FILE;
  8058. else if (aLoopTypeRead == ATTR_LOOP_UNKNOWN || line->mAttribute == ATTR_LOOP_UNKNOWN)
  8059. loop_type_read = ATTR_LOOP_UNKNOWN;
  8060. else if (aLoopTypeRead == ATTR_LOOP_NORMAL || line->mAttribute == ATTR_LOOP_NORMAL)
  8061. loop_type_read = ATTR_LOOP_NORMAL;
  8062. else if (aLoopTypeRead == ATTR_LOOP_WHILE || line->mAttribute == ATTR_LOOP_WHILE) // Lexikos: ACT_WHILE
  8063. loop_type_read = ATTR_LOOP_WHILE;
  8064. // Same as above except for PARSING loops:
  8065. loop_type_parse = ATTR_NONE;
  8066. if (aLoopTypeParse == ATTR_LOOP_PARSE || line->mAttribute == ATTR_LOOP_PARSE)
  8067. loop_type_parse = ATTR_LOOP_PARSE;
  8068. else if (aLoopTypeParse == ATTR_LOOP_UNKNOWN || line->mAttribute == ATTR_LOOP_UNKNOWN)
  8069. loop_type_parse = ATTR_LOOP_UNKNOWN;
  8070. else if (aLoopTypeParse == ATTR_LOOP_NORMAL || line->mAttribute == ATTR_LOOP_NORMAL)
  8071. loop_type_parse = ATTR_LOOP_NORMAL;
  8072. else if (aLoopTypeParse == ATTR_LOOP_WHILE || line->mAttribute == ATTR_LOOP_WHILE) // Lexikos: ACT_WHILE
  8073. loop_type_parse = ATTR_LOOP_WHILE;
  8074. // Check if the IF's action-line is something we want to recurse. UPDATE: Always
  8075. // recurse because other line types, such as Goto and Gosub, need to be preparsed
  8076. // by this function even if they are the single-line actions of an IF or an ELSE:
  8077. // Recurse this line rather than the next because we want
  8078. // the called function to recurse again if this line is a ACT_BLOCK_BEGIN
  8079. // or is itself an IF:
  8080. line_temp = PreparseIfElse(line_temp, ONLY_ONE_LINE, loop_type_file, loop_type_reg, loop_type_read
  8081. , loop_type_parse);
  8082. // If not end-of-script or error, line_temp is now either:
  8083. // 1) If this if's/loop's action was a BEGIN_BLOCK: The line after the end of the block.
  8084. // 2) If this if's/loop's action was another IF or LOOP:
  8085. // a) the line after that if's else's action; or (if it doesn't have one):
  8086. // b) the line after that if's/loop's action
  8087. // 3) If this if's/loop's action was some single-line action: the line after that action.
  8088. // In all of the above cases, line_temp is now the line where we
  8089. // would expect to find an ELSE for this IF, if it has one.
  8090. // Now the above has ensured that line_temp is this line's else, if it has one.
  8091. // Note: line_temp will be NULL if the end of the script has been reached.
  8092. // UPDATE: That can't happen now because all scripts end in ACT_EXIT:
  8093. if (line_temp == NULL) // Error or end-of-script was reached.
  8094. return NULL;
  8095. // Seems best to keep this check for mainability because changes to other checks can impact
  8096. // whether this check will ever be "true":
  8097. if (line->mRelatedLine != NULL)
  8098. return line->PreparseError("Q"); // Placeholder since it shouldn't happen. Formerly "This if-statement or LOOP unexpectedly already had an ELSE or end-point."
  8099. // Set it to the else's action, rather than the else itself, since the else itself
  8100. // is never needed during execution. UPDATE: No, instead set it to the ELSE itself
  8101. // (if it has one) since we jump here at runtime when the IF is finished (whether
  8102. // it's condition was true or false), thus skipping over any nested IF's that
  8103. // aren't in blocks beneath it. If there's no ELSE, the below value serves as
  8104. // the jumppoint we go to when the if-statement is finished. Example:
  8105. // if x
  8106. // if y
  8107. // if z
  8108. // action1
  8109. // else
  8110. // action2
  8111. // action3
  8112. // x's jumppoint should be action3 so that all the nested if's
  8113. // under the first one can be skipped after the "if x" line is recursively
  8114. // evaluated. Because of this behavior, all IFs will have a related line
  8115. // with the possibly exception of the very last if-statement in the script
  8116. // (which is possible only if the script doesn't end in a Return or Exit).
  8117. line->mRelatedLine = line_temp; // Even if <line> is a LOOP and line_temp and else?
  8118. // Even if aMode == ONLY_ONE_LINE, an IF and its ELSE count as a single
  8119. // statement (one line) due to its very nature (at least for this purpose),
  8120. // so always continue on to evaluate the IF's ELSE, if present:
  8121. if (line_temp->mActionType == ACT_ELSE)
  8122. {
  8123. if (line->mActionType == ACT_LOOP || line->mActionType == ACT_WHILE || line->mActionType == ACT_REPEAT) // Lexikos: Added check for ACT_WHILE.
  8124. {
  8125. // this can't be our else, so let the caller handle it.
  8126. if (aMode != ONLY_ONE_LINE)
  8127. // This ELSE was encountered while sequentially scanning the contents
  8128. // of a block or at the otuermost nesting layer. More thought is required
  8129. // to verify this is correct. UPDATE: This check is very old and I haven't
  8130. // found a case that can produce it yet, but until proven otherwise its safer
  8131. // to assume it's possible.
  8132. return line_temp->PreparseError(ERR_ELSE_WITH_NO_IF);
  8133. // Let the caller handle this else, since it can't be ours:
  8134. return line_temp;
  8135. }
  8136. // Now use line vs. line_temp to hold the new values, so that line_temp
  8137. // stays as a marker to the ELSE line itself:
  8138. line = line_temp->mNextLine; // Set it to the else's action line.
  8139. // Update: The following is now impossible because all scripts end in ACT_EXIT.
  8140. // Thus, it's commented out:
  8141. //if (line == NULL) // An else with no action.
  8142. // return line_temp->PreparseError("Q"); // Placeholder since impossible. Formerly "This ELSE has no action."
  8143. if (line->mActionType == ACT_ELSE || line->mActionType == ACT_BLOCK_END)
  8144. return line_temp->PreparseError("Inappropriate line beneath ELSE.");
  8145. // Assign to line rather than line_temp:
  8146. line = PreparseIfElse(line, ONLY_ONE_LINE, aLoopTypeFile, aLoopTypeReg, aLoopTypeRead
  8147. , aLoopTypeParse);
  8148. if (line == NULL)
  8149. return NULL; // Error or end-of-script.
  8150. // Set this ELSE's jumppoint. This is similar to the jumppoint set for
  8151. // an ELSEless IF, so see related comments above:
  8152. line_temp->mRelatedLine = line;
  8153. }
  8154. else // line doesn't have an else, so just continue processing from line_temp's position
  8155. line = line_temp;
  8156. // Both cases above have ensured that line is now the first line beyond the
  8157. // scope of the if-statement and that of any ELSE it may have.
  8158. if (aMode == ONLY_ONE_LINE) // Return the next unprocessed line to the caller.
  8159. return line;
  8160. // Otherwise, continue processing at line's new location:
  8161. continue;
  8162. } // ActionType is "IF".
  8163. // Since above didn't continue, do the switch:
  8164. char *line_raw_arg1 = LINE_RAW_ARG1; // Resolve only once to help reduce code size.
  8165. char *line_raw_arg2 = LINE_RAW_ARG2; //
  8166. switch (line->mActionType)
  8167. {
  8168. case ACT_BLOCK_BEGIN:
  8169. if (line->mAttribute == ATTR_TRUE) // This is the opening brace of a function definition.
  8170. sInFunctionBody = TRUE; // Must be set only for the above condition because functions can of course contain types of blocks other than the function's own block.
  8171. line = PreparseIfElse(line->mNextLine, UNTIL_BLOCK_END, aLoopTypeFile, aLoopTypeReg, aLoopTypeRead
  8172. , aLoopTypeParse);
  8173. // "line" is now either NULL due to an error, or the location of the END_BLOCK itself.
  8174. if (line == NULL)
  8175. return NULL; // Error.
  8176. break;
  8177. case ACT_BLOCK_END:
  8178. if (line->mAttribute == ATTR_TRUE) // This is the closing brace of a function definition.
  8179. sInFunctionBody = FALSE; // Must be set only for the above condition because functions can of course contain types of blocks other than the function's own block.
  8180. if (aMode == ONLY_ONE_LINE)
  8181. // Syntax error. The caller would never expect this single-line to be an
  8182. // end-block. UPDATE: I think this is impossible because callers only use
  8183. // aMode == ONLY_ONE_LINE when aStartingLine's ActionType is already
  8184. // known to be an IF or a BLOCK_BEGIN:
  8185. return line->PreparseError("Q"); // Placeholder (see above). Formerly "Unexpected end-of-block (single)."
  8186. if (UNTIL_BLOCK_END)
  8187. // Return line rather than line->mNextLine because, if we're at the end of
  8188. // the script, it's up to the caller to differentiate between that condition
  8189. // and the condition where NULL is an error indicator.
  8190. return line;
  8191. // Otherwise, we found an end-block we weren't looking for. This should be
  8192. // impossible since the block pre-parsing already balanced all the blocks?
  8193. return line->PreparseError("Q"); // Placeholder (see above). Formerly "Unexpected end-of-block (multi)."
  8194. case ACT_BREAK:
  8195. case ACT_CONTINUE:
  8196. if (!aLoopTypeFile && !aLoopTypeReg && !aLoopTypeRead && !aLoopTypeParse)
  8197. return line->PreparseError("Break/Continue must be enclosed by a Loop.");
  8198. break;
  8199. case ACT_GOSUB: // These two must be done here (i.e. *after* all the script lines have been added),
  8200. case ACT_GOTO: // so that labels both above and below each Gosub/Goto can be resolved.
  8201. if (line->ArgHasDeref(1))
  8202. // Since the jump-point contains a deref, it must be resolved at runtime:
  8203. line->mRelatedLine = NULL;
  8204. else
  8205. {
  8206. if (!line->GetJumpTarget(false))
  8207. return NULL; // Error was already displayed by called function.
  8208. if ( line->mActionType == ACT_GOSUB && sInFunctionBody
  8209. && ((Label *)(line->mRelatedLine))->mJumpToLine->IsOutsideAnyFunctionBody() ) // Relies on above call to GetJumpTarget() having set line->mRelatedLine.
  8210. // Since this Gosub and its target line are both inside a function, they must both
  8211. // be in the same function because otherwise GetJumpTarget() would have reported
  8212. // the target as invalid.
  8213. line->mAttribute = ATTR_TRUE; // v1.0.48.02: To improve runtime performance, mark this Gosub as having a target that is outside of any function body.
  8214. //else leave above at its line-constructor default of ATTR_NONE.
  8215. }
  8216. break;
  8217. // These next 4 must also be done here (i.e. *after* all the script lines have been added),
  8218. // so that labels both above and below this line can be resolved:
  8219. case ACT_ONEXIT:
  8220. if (*line_raw_arg1 && !line->ArgHasDeref(1))
  8221. if ( !(line->mAttribute = FindLabel(line_raw_arg1)) )
  8222. return line->PreparseError(ERR_NO_LABEL);
  8223. break;
  8224. case ACT_HOTKEY:
  8225. if ( *line_raw_arg2 && !line->ArgHasDeref(2)
  8226. && !line->ArgHasDeref(1) && strnicmp(line_raw_arg1, "IfWin", 5) ) // v1.0.42: Omit IfWinXX from validation.
  8227. if ( !(line->mAttribute = FindLabel(line_raw_arg2)) )
  8228. if (!Hotkey::ConvertAltTab(line_raw_arg2, true))
  8229. return line->PreparseError(ERR_NO_LABEL);
  8230. break;
  8231. case ACT_SETTIMER:
  8232. if (!line->ArgHasDeref(1))
  8233. if ( !(line->mAttribute = FindLabel(line_raw_arg1)) )
  8234. return line->PreparseError(ERR_NO_LABEL);
  8235. if (*line_raw_arg2 && !line->ArgHasDeref(2))
  8236. if (!Line::ConvertOnOff(line_raw_arg2) && !IsPureNumeric(line_raw_arg2, true) // v1.0.46.16: Allow negatives to support the new run-only-once mode.
  8237. && !line->mArg[1].is_expression) // v1.0.46.10: Don't consider expressions THAT CONTAIN NO VARIABLES OR FUNCTION-CALLS like "% 2*500" to be a syntax error.
  8238. return line->PreparseError(ERR_PARAM2_INVALID);
  8239. break;
  8240. case ACT_GROUPADD: // This must be done here because it relies on all other lines already having been added.
  8241. if (*LINE_RAW_ARG4 && !line->ArgHasDeref(4))
  8242. {
  8243. // If the label name was contained in a variable, that label is now resolved and cannot
  8244. // be changed. This is in contrast to something like "Gosub, %MyLabel%" where a change in
  8245. // the value of MyLabel will change the behavior of the Gosub at runtime:
  8246. Label *label = FindLabel(LINE_RAW_ARG4);
  8247. if (!label)
  8248. return line->PreparseError(ERR_NO_LABEL);
  8249. line->mRelatedLine = (Line *)label; // The script loader has ensured that this can't be NULL.
  8250. // Can't do this because the current line won't be the launching point for the
  8251. // Gosub. Instead, the launching point will be the GroupActivate rather than the
  8252. // GroupAdd, so it will be checked by the GroupActivate or not at all (since it's
  8253. // not that important in the case of a Gosub -- it's mostly for Goto's):
  8254. //return IsJumpValid(label->mJumpToLine);
  8255. }
  8256. break;
  8257. case ACT_ELSE:
  8258. // Should never happen because the part that handles the if's, above, should find
  8259. // all the elses and handle them. UPDATE: This happens if there's
  8260. // an extra ELSE in this scope level that has no IF:
  8261. return line->PreparseError(ERR_ELSE_WITH_NO_IF);
  8262. } // switch()
  8263. line = line->mNextLine; // If NULL due to physical end-of-script, the for-loop's condition will catch it.
  8264. if (aMode == ONLY_ONE_LINE) // Return the next unprocessed line to the caller.
  8265. // In this case, line shouldn't be (and probably can't be?) NULL because the line after
  8266. // a single-line action shouldn't be the physical end of the script. That's because
  8267. // the loader has ensured that all scripts now end in ACT_EXIT. And that final
  8268. // ACT_EXIT should never be parsed here in ONLY_ONE_LINE mode because the only time
  8269. // that mode is used is for the action of an IF, an ELSE, or possibly a LOOP.
  8270. // In all of those cases, the final ACT_EXIT line in the script (which is explicitly
  8271. // insertted by the loader) cannot be the line that was just processed by the
  8272. // switch(). Therefore, the above assignment should not have set line to NULL
  8273. // (which is good because NULL would probably be construed as "failure" by our
  8274. // caller in this case):
  8275. return line;
  8276. // else just continue the for-loop at the new value of line.
  8277. } // for()
  8278. // End of script has been reached. line is now NULL so don't dereference it.
  8279. // If we were still looking for an EndBlock to match up with a begin, that's an error.
  8280. // This indicates that the at least one BLOCK_BEGIN is missing a BLOCK_END.
  8281. // However, since the blocks were already balanced by the block pre-parsing function,
  8282. // this should be impossible unless the design of this function is flawed.
  8283. if (aMode == UNTIL_BLOCK_END)
  8284. #ifdef _DEBUG
  8285. return mLastLine->PreparseError("DEBUG: The script ended while a block was still open."); // This is a bug because the preparser already verified all blocks are balanced.
  8286. #else
  8287. return NULL; // Shouldn't happen, so just return failure.
  8288. #endif
  8289. // If we were told to process a single line, we were recursed and it should have returned above,
  8290. // so it's an error here (can happen if we were called with aStartingLine == NULL?):
  8291. if (aMode == ONLY_ONE_LINE)
  8292. return mLastLine->PreparseError("Q"); // Placeholder since probably impossible. Formerly "The script ended while an action was still expected."
  8293. // Otherwise, return something non-NULL to indicate success to the top-level caller:
  8294. return mLastLine;
  8295. }
  8296. ResultType Line::ExpressionToPostfix(ArgStruct &aArg)
  8297. // Returns OK or FAIL.
  8298. {
  8299. // Having a precedence array is required at least for SYM_POWER (since the order of evaluation
  8300. // of something like 2**1**2 does matter). It also helps performance by avoiding unnecessary pushing
  8301. // and popping of operators to the stack. This array must be kept in sync with "enum SymbolType".
  8302. // Also, dimensioning explicitly by SYM_COUNT helps enforce that at compile-time:
  8303. static UCHAR sPrecedence[SYM_COUNT] = // Performance: UCHAR vs. INT benches a little faster, perhaps due to the slight reduction in code size it causes.
  8304. {
  8305. 0,0,0,0,0,0,0 // SYM_STRING, SYM_INTEGER, SYM_FLOAT, SYM_VAR, SYM_OPERAND, SYM_DYNAMIC, SYM_BEGIN (SYM_BEGIN must be lowest precedence).
  8306. , 82, 82 // SYM_POST_INCREMENT, SYM_POST_DECREMENT: Highest precedence operator so that it will work even though it comes *after* a variable name (unlike other unaries, which come before).
  8307. , 4, 4 // SYM_CPAREN, SYM_OPAREN (to simplify the code, parentheses must be lower than all operators in precedence).
  8308. , 6 // SYM_COMMA -- Must be just above SYM_OPAREN so it doesn't pop OPARENs off the stack.
  8309. , 7,7,7,7,7,7,7,7,7,7,7,7 // SYM_ASSIGN_*. THESE HAVE AN ODD NUMBER to indicate right-to-left evaluation order, which is necessary for cascading assignments such as x:=y:=1 to work.
  8310. // , 8 // THIS VALUE MUST BE LEFT UNUSED so that the one above can be promoted to it by the infix-to-postfix routine.
  8311. , 11, 11 // SYM_IFF_ELSE, SYM_IFF_THEN (ternary conditional). HAS AN ODD NUMBER to indicate right-to-left evaluation order, which is necessary for ternaries to perform traditionally when nested in each other without parentheses.
  8312. // , 12 // THIS VALUE MUST BE LEFT UNUSED so that the one above can be promoted to it by the infix-to-postfix routine.
  8313. , 16 // SYM_OR
  8314. , 20 // SYM_AND
  8315. , 25 // SYM_LOWNOT (the word "NOT": the low precedence version of logical-not). HAS AN ODD NUMBER to indicate right-to-left evaluation order so that things like "not not var" are supports (which can be used to convert a variable into a pure 1/0 boolean value).
  8316. // , 26 // THIS VALUE MUST BE LEFT UNUSED so that the one above can be promoted to it by the infix-to-postfix routine.
  8317. , 30, 30, 30 // SYM_EQUAL, SYM_EQUALCASE, SYM_NOTEQUAL (lower prec. than the below so that "x < 5 = var" means "result of comparison is the boolean value in var".
  8318. , 34, 34, 34, 34 // SYM_GT, SYM_LT, SYM_GTOE, SYM_LTOE
  8319. , 38 // SYM_CONCAT
  8320. , 42 // SYM_BITOR -- Seems more intuitive to have these three higher in prec. than the above, unlike C and Perl, but like Python.
  8321. , 46 // SYM_BITXOR
  8322. , 50 // SYM_BITAND
  8323. , 54, 54 // SYM_BITSHIFTLEFT, SYM_BITSHIFTRIGHT
  8324. , 58, 58 // SYM_ADD, SYM_SUBTRACT
  8325. , 62, 62, 62 // SYM_MULTIPLY, SYM_DIVIDE, SYM_FLOORDIVIDE
  8326. , 67,67,67,67,67 // SYM_NEGATIVE (unary minus), SYM_HIGHNOT (the high precedence "!" operator), SYM_BITNOT, SYM_ADDRESS, SYM_DEREF
  8327. // NOTE: THE ABOVE MUST BE AN ODD NUMBER to indicate right-to-left evaluation order, which was added in v1.0.46 to support consecutive unary operators such as !*var !!var (!!var can be used to convert a value into a pure 1/0 boolean).
  8328. // , 68 // THIS VALUE MUST BE LEFT UNUSED so that the one above can be promoted to it by the infix-to-postfix routine.
  8329. , 72 // SYM_POWER (see note below). Associativity kept as left-to-right for backward compatibility (e.g. 2**2**3 is 4**3=64 not 2**8=256).
  8330. , 77, 77 // SYM_PRE_INCREMENT, SYM_PRE_DECREMENT (higher precedence than SYM_POWER because it doesn't make sense to evaluate power first because that would cause ++/-- to fail due to operating on a non-lvalue.
  8331. // , 78 // THIS VALUE MUST BE LEFT UNUSED so that the one above can be promoted to it by the infix-to-postfix routine.
  8332. // , 82, 82 // RESERVED FOR SYM_POST_INCREMENT, SYM_POST_DECREMENT (which are listed higher above for the performance of YIELDS_AN_OPERAND().
  8333. , 86 // SYM_FUNC -- Must be of highest precedence so that it stays tightly bound together as though it's a single operand for use by other operators.
  8334. };
  8335. // Most programming languages give exponentiation a higher precedence than unary minus and logical-not.
  8336. // For example, -2**2 is evaluated as -(2**2), not (-2)**2 (the latter is unsupported by qmathPow anyway).
  8337. // However, this rule requires a small workaround in the postfix-builder to allow 2**-2 to be
  8338. // evaluated as 2**(-2) rather than being seen as an error. v1.0.45: A similar thing is required
  8339. // to allow the following to work: 2**!1, 2**not 0, 2**~0xFFFFFFFE, 2**&x.
  8340. // On a related note, the right-to-left tradition of something like 2**3**4 is not implemented (maybe in v2).
  8341. // Instead, the expression is evaluated from left-to-right (like other operators) to simplify the code.
  8342. ExprTokenType infix[MAX_TOKENS], *postfix[MAX_TOKENS], *stack[MAX_TOKENS + 1]; // +1 for SYM_BEGIN on the stack.
  8343. int infix_count = 0, postfix_count = 0, stack_count = 0;
  8344. // Above dimensions the stack to be as large as the infix/postfix arrays to cover worst-case
  8345. // scenarios and avoid having to check for overflow. For the infix-to-postfix conversion, the
  8346. // stack must be large enough to hold a malformed expression consisting entirely of operators
  8347. // (though other checks might prevent this). It must also be large enough for use by the final
  8348. // expression evaluation phase, the worst case of which is unknown but certainly not larger
  8349. // than MAX_TOKENS.
  8350. ///////////////////////////////////////////////////////////////////////////////////////////////
  8351. // TOKENIZE THE INFIX EXPRESSION INTO AN INFIX ARRAY: Avoids the performance overhead of having
  8352. // to re-detect whether each symbol is an operand vs. operator at multiple stages.
  8353. ///////////////////////////////////////////////////////////////////////////////////////////////
  8354. // In v1.0.46.01, this section was simplified to avoid transcribing the entire expression into the
  8355. // deref buffer. In addition to improving performance and reducing code size, this also solves
  8356. // obscure timing bugs caused by functions that have side-effects, especially in comma-separated
  8357. // sub-expressions. In these cases, one part of an expression could change a built-in variable
  8358. // (indirectly or in the case of Clipboard, directly), an environment variable, or a double-def.
  8359. // For example the dynamic components of a double-deref can be changed by other parts of an
  8360. // expression, even one without commas. Another example is: fn(clipboard, func_that_changes_clip()).
  8361. // So now, built-in & environment variables and double-derefs are resolve when they're actually
  8362. // encountered during the final/evaluation phase.
  8363. // Another benefit to deferring the resolution of these types of items is that they become eligible
  8364. // for short-circuiting, which further helps performance (they're quite similar to built-in
  8365. // functions in this respect).
  8366. char *op_end, *cp;
  8367. DerefType *deref, *this_deref, *deref_start, *deref_new;
  8368. int derefs_in_this_double;
  8369. int cp1; // int vs. char benchmarks slightly faster, and is slightly smaller in code size.
  8370. for (cp = aArg.text, deref = aArg.deref // Start at the begining of this arg's text and look for the next deref.
  8371. ;; ++deref, ++infix_count) // FOR EACH DEREF IN AN ARG:
  8372. {
  8373. this_deref = deref && deref->marker ? deref : NULL; // A deref with a NULL marker terminates the list (i.e. the final deref isn't a deref, merely a terminator of sorts.
  8374. // BEFORE PROCESSING "this_deref" ITSELF, MUST FIRST PROCESS ANY LITERAL/RAW TEXT THAT LIES TO ITS LEFT.
  8375. if (this_deref && cp < this_deref->marker // There's literal/raw text to the left of the next deref.
  8376. || !this_deref && *cp) // ...or there's no next deref, but there's some literal raw text remaining to be processed.
  8377. {
  8378. for (;; ++infix_count) // FOR EACH TOKEN INSIDE THIS RAW/LITERAL TEXT SECTION.
  8379. {
  8380. // Because neither the postfix array nor the stack can ever wind up with more tokens than were
  8381. // contained in the original infix array, only the infix array need be checked for overflow:
  8382. if (infix_count > MAX_TOKENS - 1) // No room for this operator or operand to be added.
  8383. return LineError(ERR_EXPR_TOO_LONG);
  8384. // Only spaces and tabs are considered whitespace, leaving newlines and other whitespace characters
  8385. // for possible future use:
  8386. cp = omit_leading_whitespace(cp);
  8387. if (!*cp // Very end of expression...
  8388. || this_deref && cp >= this_deref->marker) // ...or no more literal/raw text left to process at the left side of this_deref.
  8389. break; // Break out of inner loop so that bottom of the outer loop will process this_deref itself.
  8390. ExprTokenType &this_infix_item = infix[infix_count]; // Might help reduce code size since it's referenced many places below.
  8391. // CHECK IF THIS CHARACTER IS AN OPERATOR.
  8392. cp1 = cp[1]; // Improves performance by nearly 5% and appreciably reduces code size (at the expense of being less maintainable).
  8393. switch (*cp)
  8394. {
  8395. // The most common cases are kept up top to enhance performance if switch() is implemented as if-else ladder.
  8396. case '+':
  8397. if (cp1 == '=')
  8398. {
  8399. ++cp; // An additional increment to have loop skip over the operator's second symbol.
  8400. this_infix_item.symbol = SYM_ASSIGN_ADD;
  8401. }
  8402. else
  8403. {
  8404. if (infix_count && YIELDS_AN_OPERAND(infix[infix_count - 1].symbol))
  8405. {
  8406. if (cp1 == '+')
  8407. {
  8408. // For consistency, assume that since the previous item is an operand (even if it's
  8409. // ')'), this is a post-op that applies to that operand. For example, the following
  8410. // are all treated the same for consistency (implicit concatention where the '.'
  8411. // is omitted is rare anyway).
  8412. // x++ y
  8413. // x ++ y
  8414. // x ++y
  8415. // The following implicit concat is deliberately unsupported:
  8416. // "string" ++x
  8417. // The ++ above is seen as applying to the string because it doesn't seem worth
  8418. // the complexity to distinguish between expressions that can accept a post-op
  8419. // and those that can't (operands other than variables can have a post-op;
  8420. // e.g. (x:=y)++).
  8421. ++cp; // An additional increment to have loop skip over the operator's second symbol.
  8422. this_infix_item.symbol = SYM_POST_INCREMENT;
  8423. }
  8424. else
  8425. this_infix_item.symbol = SYM_ADD;
  8426. }
  8427. else if (cp1 == '+') // Pre-increment.
  8428. {
  8429. ++cp; // An additional increment to have loop skip over the operator's second symbol.
  8430. this_infix_item.symbol = SYM_PRE_INCREMENT;
  8431. }
  8432. else // Remove unary pluses from consideration since they do not change the calculation.
  8433. --infix_count; // Counteract the loop's increment.
  8434. }
  8435. break;
  8436. case '-':
  8437. if (cp1 == '=')
  8438. {
  8439. ++cp; // An additional increment to have loop skip over the operator's second symbol.
  8440. this_infix_item.symbol = SYM_ASSIGN_SUBTRACT;
  8441. break;
  8442. }
  8443. // Otherwise (since above didn't "break"):
  8444. // Must allow consecutive unary minuses because otherwise, the following example
  8445. // would not work correctly when y contains a negative value: var := 3 * -y
  8446. if (infix_count && YIELDS_AN_OPERAND(infix[infix_count - 1].symbol))
  8447. {
  8448. if (cp1 == '-')
  8449. {
  8450. // See comments at SYM_POST_INCREMENT about this section.
  8451. ++cp; // An additional increment to have loop skip over the operator's second symbol.
  8452. this_infix_item.symbol = SYM_POST_DECREMENT;
  8453. }
  8454. else
  8455. this_infix_item.symbol = SYM_SUBTRACT;
  8456. }
  8457. else if (cp1 == '-') // Pre-decrement.
  8458. {
  8459. ++cp; // An additional increment to have loop skip over the operator's second symbol.
  8460. this_infix_item.symbol = SYM_PRE_DECREMENT;
  8461. }
  8462. else // Unary minus.
  8463. {
  8464. // Set default for cases where the processing below this line doesn't determine
  8465. // it's a negative numeric literal:
  8466. this_infix_item.symbol = SYM_NEGATIVE;
  8467. // v1.0.40.06: The smallest signed 64-bit number (-0x8000000000000000) wasn't properly
  8468. // supported in previous versions because its unary minus was being seen as an operator,
  8469. // and thus the raw number was being passed as a positive to _atoi64() or _strtoi64(),
  8470. // neither of which would recognize it as a valid value. To correct this, a unary
  8471. // minus followed by a raw numeric literal is now treated as a single literal number
  8472. // rather than unary minus operator followed by a positive number.
  8473. //
  8474. // To be a valid "literal negative number", the character immediately following
  8475. // the unary minus must not be:
  8476. // 1) Whitespace (atoi() and such don't support it, nor is it at all conventional).
  8477. // 2) An open-parenthesis such as the one in -(x).
  8478. // 3) Another unary minus or operator such as --x (which is the pre-decrement operator).
  8479. // To cover the above and possibly other unforeseen things, insist that the first
  8480. // character be a digit (even a hex literal must start with 0).
  8481. if ((cp1 >= '0' && cp1 <= '9') || cp1 == '.') // v1.0.46.01: Recognize dot too, to support numbers like -.5.
  8482. {
  8483. for (op_end = cp + 2; !strchr(EXPR_OPERAND_TERMINATORS, *op_end); ++op_end); // Find the end of this number (can be '\0').
  8484. // 1.0.46.11: Due to obscurity, no changes have been made here to support scientific
  8485. // notation followed by the power operator; e.g. -1.0e+1**5.
  8486. if (!this_deref || op_end < this_deref->marker) // Detect numeric double derefs such as one created via "12%i% = value".
  8487. {
  8488. // Because the power operator takes precedence over unary minus, don't collapse
  8489. // unary minus into a literal numeric literal if the number is immediately
  8490. // followed by the power operator. This is correct behavior even for
  8491. // -0x8000000000000000 because -0x8000000000000000**2 would in fact be undefined
  8492. // because ** is higher precedence than unary minus and +0x8000000000000000 is
  8493. // beyond the signed 64-bit range. SEE ALSO the comments higher above.
  8494. // Use a temp variable because numeric_literal requires that op_end be set properly:
  8495. char *pow_temp = omit_leading_whitespace(op_end);
  8496. if (!(pow_temp[0] == '*' && pow_temp[1] == '*'))
  8497. goto numeric_literal; // Goto is used for performance and also as a patch to minimize the chance of breaking other things via redesign.
  8498. //else it's followed by pow. Since pow is higher precedence than unary minus,
  8499. // leave this unary minus as an operator so that it will take effect after the pow.
  8500. }
  8501. //else possible double deref, so leave this unary minus as an operator.
  8502. }
  8503. } // Unary minus.
  8504. break;
  8505. case ',':
  8506. this_infix_item.symbol = SYM_COMMA; // Used to separate sub-statements and function parameters.
  8507. break;
  8508. case '/':
  8509. if (cp1 == '=')
  8510. {
  8511. ++cp; // An additional increment to have loop skip over the operator's second symbol.
  8512. this_infix_item.symbol = SYM_ASSIGN_DIVIDE;
  8513. }
  8514. else if (cp1 == '/')
  8515. {
  8516. if (cp[2] == '=')
  8517. {
  8518. cp += 2; // An additional increment to have loop skip over the operator's 2nd & 3rd symbols.
  8519. this_infix_item.symbol = SYM_ASSIGN_FLOORDIVIDE;
  8520. }
  8521. else
  8522. {
  8523. ++cp; // An additional increment to have loop skip over the second '/' too.
  8524. this_infix_item.symbol = SYM_FLOORDIVIDE;
  8525. }
  8526. }
  8527. else
  8528. this_infix_item.symbol = SYM_DIVIDE;
  8529. break;
  8530. case '*':
  8531. if (cp1 == '=')
  8532. {
  8533. ++cp; // An additional increment to have loop skip over the operator's second symbol.
  8534. this_infix_item.symbol = SYM_ASSIGN_MULTIPLY;
  8535. }
  8536. else
  8537. {
  8538. if (cp1 == '*') // Python, Perl, and other languages also use ** for power.
  8539. {
  8540. ++cp; // An additional increment to have loop skip over the second '*' too.
  8541. this_infix_item.symbol = SYM_POWER;
  8542. }
  8543. else
  8544. {
  8545. // Differentiate between unary dereference (*) and the "multiply" operator:
  8546. // See '-' above for more details:
  8547. this_infix_item.symbol = (infix_count && YIELDS_AN_OPERAND(infix[infix_count - 1].symbol))
  8548. ? SYM_MULTIPLY : SYM_DEREF;
  8549. }
  8550. }
  8551. break;
  8552. case '!':
  8553. if (cp1 == '=') // i.e. != is synonymous with <>, which is also already supported by legacy.
  8554. {
  8555. ++cp; // An additional increment to have loop skip over the '=' too.
  8556. this_infix_item.symbol = SYM_NOTEQUAL;
  8557. }
  8558. else
  8559. // If what lies to its left is a CPARAN or OPERAND, SYM_CONCAT is not auto-inserted because:
  8560. // 1) Allows ! and ~ to potentially be overloaded to become binary and unary operators in the future.
  8561. // 2) Keeps the behavior consistent with unary minus, which could never auto-concat since it would
  8562. // always be seen as the binary subtract operator in such cases.
  8563. // 3) Simplifies the code.
  8564. this_infix_item.symbol = SYM_HIGHNOT; // High-precedence counterpart of the word "not".
  8565. break;
  8566. case '(':
  8567. // The below should not hurt any future type-casting feature because the type-cast can be checked
  8568. // for prior to checking the below. For example, if what immediately follows the open-paren is
  8569. // the string "int)", this symbol is not open-paren at all but instead the unary type-cast-to-int
  8570. // operator.
  8571. if (infix_count && YIELDS_AN_OPERAND(infix[infix_count - 1].symbol)) // If it's an operand, at this stage it can only be SYM_OPERAND or SYM_STRING.
  8572. {
  8573. if (infix_count > MAX_TOKENS - 2) // -2 to ensure room for this operator and the operand further below.
  8574. return LineError(ERR_EXPR_TOO_LONG);
  8575. this_infix_item.symbol = SYM_CONCAT;
  8576. ++infix_count;
  8577. }
  8578. infix[infix_count].symbol = SYM_OPAREN; // MUST NOT REFER TO this_infix_item IN CASE ABOVE DID ++infix_count.
  8579. break;
  8580. case ')':
  8581. this_infix_item.symbol = SYM_CPAREN;
  8582. break;
  8583. case '=':
  8584. if (cp1 == '=')
  8585. {
  8586. ++cp; // An additional increment to have loop skip over the other '=' too.
  8587. this_infix_item.symbol = SYM_EQUALCASE;
  8588. }
  8589. else
  8590. this_infix_item.symbol = SYM_EQUAL;
  8591. break;
  8592. case '>':
  8593. switch (cp1)
  8594. {
  8595. case '=':
  8596. ++cp; // An additional increment to have loop skip over the '=' too.
  8597. this_infix_item.symbol = SYM_GTOE;
  8598. break;
  8599. case '>':
  8600. if (cp[2] == '=')
  8601. {
  8602. cp += 2; // An additional increment to have loop skip over the operator's 2nd & 3rd symbols.
  8603. this_infix_item.symbol = SYM_ASSIGN_BITSHIFTRIGHT;
  8604. }
  8605. else
  8606. {
  8607. ++cp; // An additional increment to have loop skip over the second '>' too.
  8608. this_infix_item.symbol = SYM_BITSHIFTRIGHT;
  8609. }
  8610. break;
  8611. default:
  8612. this_infix_item.symbol = SYM_GT;
  8613. }
  8614. break;
  8615. case '<':
  8616. switch (cp1)
  8617. {
  8618. case '=':
  8619. ++cp; // An additional increment to have loop skip over the '=' too.
  8620. this_infix_item.symbol = SYM_LTOE;
  8621. break;
  8622. case '>':
  8623. ++cp; // An additional increment to have loop skip over the '>' too.
  8624. this_infix_item.symbol = SYM_NOTEQUAL;
  8625. break;
  8626. case '<':
  8627. if (cp[2] == '=')
  8628. {
  8629. cp += 2; // An additional increment to have loop skip over the operator's 2nd & 3rd symbols.
  8630. this_infix_item.symbol = SYM_ASSIGN_BITSHIFTLEFT;
  8631. }
  8632. else
  8633. {
  8634. ++cp; // An additional increment to have loop skip over the second '<' too.
  8635. this_infix_item.symbol = SYM_BITSHIFTLEFT;
  8636. }
  8637. break;
  8638. default:
  8639. this_infix_item.symbol = SYM_LT;
  8640. }
  8641. break;
  8642. case '&':
  8643. if (cp1 == '&')
  8644. {
  8645. ++cp; // An additional increment to have loop skip over the second '&' too.
  8646. this_infix_item.symbol = SYM_AND;
  8647. }
  8648. else if (cp1 == '=')
  8649. {
  8650. ++cp; // An additional increment to have loop skip over the operator's second symbol.
  8651. this_infix_item.symbol = SYM_ASSIGN_BITAND;
  8652. }
  8653. else
  8654. {
  8655. // Differentiate between unary "take the address of" and the "bitwise and" operator:
  8656. // See '-' above for more details:
  8657. this_infix_item.symbol = (infix_count && YIELDS_AN_OPERAND(infix[infix_count - 1].symbol))
  8658. ? SYM_BITAND : SYM_ADDRESS;
  8659. }
  8660. break;
  8661. case '|':
  8662. if (cp1 == '|')
  8663. {
  8664. ++cp; // An additional increment to have loop skip over the second '|' too.
  8665. this_infix_item.symbol = SYM_OR;
  8666. }
  8667. else if (cp1 == '=')
  8668. {
  8669. ++cp; // An additional increment to have loop skip over the operator's second symbol.
  8670. this_infix_item.symbol = SYM_ASSIGN_BITOR;
  8671. }
  8672. else
  8673. this_infix_item.symbol = SYM_BITOR;
  8674. break;
  8675. case '^':
  8676. if (cp1 == '=')
  8677. {
  8678. ++cp; // An additional increment to have loop skip over the operator's second symbol.
  8679. this_infix_item.symbol = SYM_ASSIGN_BITXOR;
  8680. }
  8681. else
  8682. this_infix_item.symbol = SYM_BITXOR;
  8683. break;
  8684. case '~':
  8685. // If what lies to its left is a CPARAN or OPERAND, SYM_CONCAT is not auto-inserted because:
  8686. // 1) Allows ! and ~ to potentially be overloaded to become binary and unary operators in the future.
  8687. // 2) Keeps the behavior consistent with unary minus, which could never auto-concat since it would
  8688. // always be seen as the binary subtract operator in such cases.
  8689. // 3) Simplifies the code.
  8690. this_infix_item.symbol = SYM_BITNOT;
  8691. break;
  8692. case '?':
  8693. this_infix_item.symbol = SYM_IFF_THEN;
  8694. break;
  8695. case ':':
  8696. if (cp1 == '=')
  8697. {
  8698. ++cp; // An additional increment to have loop skip over the second '|' too.
  8699. this_infix_item.symbol = SYM_ASSIGN;
  8700. }
  8701. else
  8702. this_infix_item.symbol = SYM_IFF_ELSE;
  8703. break;
  8704. case '"': // QUOTED/LITERAL STRING.
  8705. // Note that single and double-derefs are impossible inside string-literals
  8706. // because the load-time deref parser would never detect anything inside
  8707. // of quotes -- even non-escaped percent signs -- as derefs.
  8708. if (infix_count && YIELDS_AN_OPERAND(infix[infix_count - 1].symbol)) // If it's an operand, at this stage it can only be SYM_OPERAND or SYM_STRING.
  8709. {
  8710. if (infix_count > MAX_TOKENS - 2) // -2 to ensure room for this operator and the operand further below.
  8711. return LineError(ERR_EXPR_TOO_LONG);
  8712. this_infix_item.symbol = SYM_CONCAT;
  8713. ++infix_count;
  8714. }
  8715. // The following section is nearly identical to one in DefineFunc().
  8716. // Find the end of this string literal, noting that a pair of double quotes is
  8717. // a literal double quote inside the string:
  8718. for (op_end = ++cp;;) // Omit the starting-quote from consideration, and from the resulting/built string.
  8719. {
  8720. if (!*op_end) // No matching end-quote. Probably impossible due to load-time validation.
  8721. return LineError(ERR_MISSING_CLOSE_QUOTE); // Since this error string is used in other places, compiler string pooling should result in little extra memory needed for this line.
  8722. if (*op_end == '"') // And if it's not followed immediately by another, this is the end of it.
  8723. {
  8724. ++op_end;
  8725. if (*op_end != '"') // String terminator or some non-quote character.
  8726. break; // The previous char is the ending quote.
  8727. //else a pair of quotes, which resolves to a single literal quote. So fall through
  8728. // to the below, which will copy of quote character to the buffer. Then this pair
  8729. // is skipped over and the loop continues until the real end-quote is found.
  8730. }
  8731. //else some character other than '\0' or '"'.
  8732. ++op_end;
  8733. }
  8734. // Since above didn't "goto", op_end is now the character after the ending '"'.
  8735. // MUST NOT REFER TO this_infix_item IN CASE HIGHER ABOVE DID ++infix_count:
  8736. infix[infix_count].symbol = SYM_STRING; // Marked explicitly as string vs. SYM_OPERAND to prevent it from being seen as a number, e.g. if (var == "12.0") would be false if var contains "12" with no trailing ".0".
  8737. if ( !(infix[infix_count].marker = SimpleHeap::Malloc(cp, op_end - cp - 1)) ) // -1 to omit the ending quote. cp was already adjusted to omit the starting quote.
  8738. return LineError(ERR_OUTOFMEM);
  8739. StrReplace(infix[infix_count].marker, "\"\"", "\"", SCS_SENSITIVE); // Resolve each "" into a single ". Consequently, a little bit of memory in "marker" might be wasted, but it doesn't seem worth the code size to compensate for this.
  8740. cp = op_end; // Have the loop process whatever lies at op_end and beyond.
  8741. continue; // Continue vs. break to avoid the ++cp at the bottom. Above has already set cp to be the character after this literal string's close-quote.
  8742. default: // NUMERIC-LITERAL, DOUBLE-DEREF, RELATIONAL OPERATOR SUCH AS "NOT", OR UNRECOGNIZED SYMBOL.
  8743. if (*cp == '.') // This one must be done here rather than as a "case". See comment below.
  8744. {
  8745. if (cp1 == '=')
  8746. {
  8747. ++cp; // An additional increment to have loop skip over the operator's second symbol.
  8748. this_infix_item.symbol = SYM_ASSIGN_CONCAT;
  8749. break;
  8750. }
  8751. if (IS_SPACE_OR_TAB(cp1))
  8752. {
  8753. this_infix_item.symbol = SYM_CONCAT;
  8754. break;
  8755. }
  8756. //else this is a '.' that isn't followed by a space, tab, or '='. So it's probably
  8757. // a number without a leading zero like .2, so continue on below to process it.
  8758. // BACKWARD COMPATIBILITY: The above behavior creates ambiguity between a "pure"
  8759. // concat operator (.) and numbers that begin with a decimal point. I think that
  8760. // came about because the concat operator was added after numbers like .5 had been
  8761. // supported a long time. In any case, it's documented that the '.' operator must
  8762. // have a space on both sides to be valid, and maybe automatic/implicit concatenation
  8763. // handles most such situations properly anyway (e.g. the expression "x .5").
  8764. }
  8765. // Find the end of this operand or keyword, even if that end extended into the next deref.
  8766. // StrChrAny() is not used because if *op_end is '\0', the strchr() below will find it too:
  8767. for (op_end = cp + 1; !strchr(EXPR_OPERAND_TERMINATORS, *op_end); ++op_end);
  8768. // Now op_end marks the end of this operand or keyword. That end might be the zero terminator
  8769. // or the next operator in the expression, or just a whitespace.
  8770. if (this_deref && op_end >= this_deref->marker)
  8771. goto double_deref; // This also serves to break out of the inner for(), equivalent to a break.
  8772. // Otherwise, this operand is a normal raw numeric-literal or a word-operator (and/or/not).
  8773. // The section below is very similar to the one used at load-time to recognize and/or/not,
  8774. // so it should be maintained with that section. UPDATE for v1.0.45: The load-time parser
  8775. // now resolves "OR" to || and "AND" to && to improve runtime performance and reduce code size here.
  8776. // However, "NOT" but still be parsed here at runtime because it's not quite the same as the "!"
  8777. // operator (different precedence), and it seemed too much trouble to invent some special
  8778. // operator symbol for load-time to insert as a placeholder/substitute (especially since that
  8779. // symbol would appear in ListLines).
  8780. if (op_end-cp == 3
  8781. && (cp[0] == 'n' || cp[0] == 'N')
  8782. && ( cp1 == 'o' || cp1 == 'O')
  8783. && (cp[2] == 't' || cp[2] == 'T')) // "NOT" was found.
  8784. {
  8785. this_infix_item.symbol = SYM_LOWNOT;
  8786. cp = op_end; // Have the loop process whatever lies at op_end and beyond.
  8787. continue; // Continue vs. break to avoid the ++cp at the bottom (though it might not matter in this case).
  8788. }
  8789. numeric_literal:
  8790. // Since above didn't "continue", this item is probably a raw numeric literal (either SYM_FLOAT
  8791. // or SYM_INTEGER, to be differentiated later) because just about every other possibility has
  8792. // been ruled out above. For example, unrecognized symbols should be impossible at this stage
  8793. // because load-time validation would have caught them. And any kind of unquoted alphanumeric
  8794. // characters (other than "NOT", which was detected above) wouldn't have reached this point
  8795. // because load-time pre-parsing would have marked it as a deref/var, not raw/literal text.
  8796. if ( toupper(op_end[-1]) == 'E' // v1.0.46.11: It looks like scientific notation...
  8797. && !(cp[0] == '0' && toupper(cp[1]) == 'X') // ...and it's not a hex number (this check avoids falsely detecting hex numbers that end in 'E' as exponents). This line fixed in v1.0.46.12.
  8798. && !(cp[0] == '-' && cp[1] == '0' && toupper(cp[2]) == 'X') // ...and it's not a negative hex number (this check avoids falsely detecting hex numbers that end in 'E' as exponents). This line added as a fix in v1.0.47.03.
  8799. )
  8800. {
  8801. // Since op_end[-1] is the 'E' or an exponent, the only valid things for op_end[0] to be
  8802. // are + or - (it can't be a digit because the loop above would never have stopped op_end
  8803. // at a digit). If it isn't + or -, it's some kind of syntax error, so doing the following
  8804. // seems harmless in any case:
  8805. do // Skip over the sign and its exponent; e.g. the "+1" in "1.0e+1". There must be a sign in this particular sci-notation number or we would never have arrived here.
  8806. ++op_end;
  8807. while (*op_end >= '0' && *op_end <= '9'); // Avoid isdigit() because it sometimes causes a debug assertion failure at: (unsigned)(c + 1) <= 256 (probably only in debug mode), and maybe only when bad data got in it due to some other bug.
  8808. }
  8809. if (infix_count && YIELDS_AN_OPERAND(infix[infix_count - 1].symbol)) // If it's an operand, at this stage it can only be SYM_OPERAND or SYM_STRING.
  8810. {
  8811. if (infix_count > MAX_TOKENS - 2) // -2 to ensure room for this operator and the operand further below.
  8812. return LineError(ERR_EXPR_TOO_LONG);
  8813. this_infix_item.symbol = SYM_CONCAT;
  8814. ++infix_count;
  8815. }
  8816. // MUST NOT REFER TO this_infix_item IN CASE ABOVE DID ++infix_count:
  8817. infix[infix_count].symbol = SYM_OPERAND;
  8818. if ( !(infix[infix_count].marker = SimpleHeap::Malloc(cp, op_end - cp)) )
  8819. return LineError(ERR_OUTOFMEM);
  8820. cp = op_end; // Have the loop process whatever lies at op_end and beyond.
  8821. continue; // "Continue" to avoid the ++cp at the bottom.
  8822. } // switch() for type of symbol/operand.
  8823. ++cp; // i.e. increment only if a "continue" wasn't encountered somewhere above. Although maintainability is reduced to do this here, it avoids dozens of ++cp in other places.
  8824. } // for each token in this section of raw/literal text.
  8825. } // End of processing of raw/literal text (such as operators) that lie to the left of this_deref.
  8826. if (!this_deref) // All done because the above just processed all the raw/literal text (if any) that
  8827. break; // lay to the right of the last deref.
  8828. // THE ABOVE HAS NOW PROCESSED ANY/ALL RAW/LITERAL TEXT THAT LIES TO THE LEFT OF this_deref.
  8829. // SO NOW PROCESS THIS_DEREF ITSELF.
  8830. if (infix_count > MAX_TOKENS - 1) // No room for the deref item below to be added.
  8831. return LineError(ERR_EXPR_TOO_LONG);
  8832. DerefType &this_deref_ref = *this_deref; // Boosts performance slightly.
  8833. if (this_deref_ref.is_function) // Above has ensured that at this stage, this_deref!=NULL.
  8834. {
  8835. if (infix_count && YIELDS_AN_OPERAND(infix[infix_count - 1].symbol)) // If it's an operand, at this stage it can only be SYM_OPERAND or SYM_STRING.
  8836. {
  8837. if (infix_count > MAX_TOKENS - 2) // -2 to ensure room for this operator and the operand further below.
  8838. return LineError(ERR_EXPR_TOO_LONG);
  8839. infix[infix_count++].symbol = SYM_CONCAT;
  8840. }
  8841. infix[infix_count].symbol = SYM_FUNC;
  8842. infix[infix_count].deref = this_deref;
  8843. }
  8844. else // this_deref is a variable.
  8845. {
  8846. if (*this_deref_ref.marker == g_DerefChar) // A double-deref because normal derefs don't start with '%'.
  8847. {
  8848. // Find the end of this operand, even if that end extended into the next deref.
  8849. // StrChrAny() is not used because if *op_end is '\0', the strchr() below will find it too:
  8850. for (op_end = this_deref_ref.marker + this_deref_ref.length; !strchr(EXPR_OPERAND_TERMINATORS, *op_end); ++op_end);
  8851. goto double_deref;
  8852. }
  8853. else
  8854. {
  8855. if (infix_count && YIELDS_AN_OPERAND(infix[infix_count - 1].symbol)) // If it's an operand, at this stage it can only be SYM_OPERAND or SYM_STRING.
  8856. {
  8857. if (infix_count > MAX_TOKENS - 2) // -2 to ensure room for this operator and the operand further below.
  8858. return LineError(ERR_EXPR_TOO_LONG);
  8859. infix[infix_count++].symbol = SYM_CONCAT;
  8860. }
  8861. if (this_deref_ref.var->Type() == VAR_NORMAL // VAR_ALIAS is taken into account (and resolved) by Type().
  8862. && g_NoEnv) // v1.0.43.08: Added g_NoEnv. Relies on short-circuit boolean order.
  8863. // "!this_deref_ref.var->Get()" isn't checked here. See comments in SYM_DYNAMIC evaluation.
  8864. {
  8865. // DllCall() and possibly others rely on this having been done to support changing the
  8866. // value of a parameter (similar to by-ref).
  8867. infix[infix_count].symbol = SYM_VAR; // Type() is VAR_NORMAL as verified above; but SYM_VAR can be the clipboard in the case of expression lvalues. Search for VAR_CLIPBOARD further below for details.
  8868. }
  8869. else // It's either a built-in variable (including clipboard) OR a possible environment variable.
  8870. {
  8871. infix[infix_count].symbol = SYM_DYNAMIC;
  8872. infix[infix_count].buf = NULL; // SYM_DYNAMIC requires that buf be set to NULL for non-double-deref vars (since there are two different types of SYM_DYNAMIC).
  8873. }
  8874. infix[infix_count].var = this_deref_ref.var;
  8875. }
  8876. } // Handling of the var or function in this_deref.
  8877. // Finally, jump over the dereference text. Note that in the case of an expression, there might not
  8878. // be any percent signs within the text of the dereference, e.g. x + y, not %x% + %y% (unless they're
  8879. // deliberately double-derefs).
  8880. cp += this_deref_ref.length;
  8881. // The outer loop will now do ++infix for us.
  8882. continue; // To avoid falling into the label below. The label below is only reached by explicit goto.
  8883. double_deref: // Caller has set cp to be start and op_end to be the character after the last one of the double deref.
  8884. if (infix_count && YIELDS_AN_OPERAND(infix[infix_count - 1].symbol)) // If it's an operand, at this stage it can only be SYM_OPERAND or SYM_STRING.
  8885. {
  8886. if (infix_count > MAX_TOKENS - 2) // -2 to ensure room for this operator and the operand further below.
  8887. return LineError(ERR_EXPR_TOO_LONG);
  8888. infix[infix_count++].symbol = SYM_CONCAT;
  8889. }
  8890. infix[infix_count].symbol = SYM_DYNAMIC;
  8891. if ( !(infix[infix_count].buf = SimpleHeap::Malloc(cp, op_end - cp)) ) // Example string: "Array%i%"
  8892. return LineError(ERR_OUTOFMEM);
  8893. // Set "deref" properly for the loop to resume processing at the item after this double deref.
  8894. // Callers of double_deref have ensured that deref!=NULL and deref->marker!=NULL (because it
  8895. // doesn't make sense to have a double-deref unless caller discovered the first deref that
  8896. // belongs to this double deref, such as the "i" in Array%i%).
  8897. for (deref_start = deref, ++deref; deref->marker && deref->marker < op_end; ++deref);
  8898. derefs_in_this_double = (int)(deref - deref_start);
  8899. --deref; // Compensate for the outer loop's ++deref.
  8900. // There's insufficient room to shoehorn all the necessary data into the token (since circuit_token probably
  8901. // can't be safely overloaded at this stage), so allocate a little bit of stack memory, just enough for the
  8902. // number of derefs (variables) whose contents comprise the name of this double-deref variable (typically
  8903. // there's only one; e.g. the "i" in Array%i%).
  8904. if ( !(deref_new = (DerefType *)SimpleHeap::Malloc((derefs_in_this_double + 1) * sizeof(DerefType))) ) // Provides one extra at the end as a terminator.
  8905. return LineError(ERR_OUTOFMEM);
  8906. memcpy(deref_new, deref_start, derefs_in_this_double * sizeof(DerefType));
  8907. deref_new[derefs_in_this_double].marker = NULL; // Put a NULL in the last item, which terminates the array.
  8908. for (deref_start = deref_new; deref_start->marker; ++deref_start)
  8909. deref_start->marker = infix[infix_count].buf + (deref_start->marker - cp); // Point each to its position in the *new* buf.
  8910. infix[infix_count].var = (Var *)deref_new; // Postfix evaluation uses this to build the variable's name dynamically.
  8911. if (*op_end == '(') // i.e. dynamic function call (v1.0.47.06)
  8912. {
  8913. if (infix_count > MAX_TOKENS - 2) // No room for the following symbol to be added (plus the ++infix done that will be done by the outer loop).
  8914. return LineError(ERR_EXPR_TOO_LONG);
  8915. deref_start->is_function = true; // As a result of the loop above, deref_start is the null-marker deref which terminates the deref list.
  8916. deref_start->param_count = deref_new->param_count; // param_count was set when the derefs were parsed.
  8917. ++infix_count; // THIS CREATES ANOTHER TOKEN for the function call itself. Order in infix is SYM_DYNAMIC + SYM_FUNC + (parameter tokens/operators).
  8918. infix[infix_count].symbol = SYM_FUNC;
  8919. infix[infix_count].deref = deref_start; // See comment below.
  8920. // The trick here is that this SYM_FUNC now points to one of the same deref items that the
  8921. // corresponding SYM_DYNAMIC does. During postfix evaluation, that allows SYM_DYNAMIC to update
  8922. // the attributes of that deref so that when the SYM_FUNC is executed, it will know which function
  8923. // to call.
  8924. }
  8925. else
  8926. deref_start->is_function = false;
  8927. cp = op_end; // Must be done only after above is done using cp: Set things up for the next iteration.
  8928. // The outer loop will now do ++infix for us.
  8929. } // For each deref in this expression, and also for the final literal/raw text to the right of the last deref.
  8930. // Terminate the array with a special item. This allows infix-to-postfix conversion to do a faster
  8931. // traversal of the infix array.
  8932. if (infix_count > MAX_TOKENS - 1) // No room for the following symbol to be added.
  8933. return LineError(ERR_EXPR_TOO_LONG);
  8934. infix[infix_count].symbol = SYM_INVALID;
  8935. ////////////////////////////
  8936. // CONVERT INFIX TO POSTFIX.
  8937. ////////////////////////////
  8938. // SYM_BEGIN is the first item to go on the stack. It's a flag to indicate that conversion to postfix has begun:
  8939. ExprTokenType token_begin;
  8940. token_begin.symbol = SYM_BEGIN;
  8941. STACK_PUSH(&token_begin);
  8942. SymbolType stack_symbol, infix_symbol, sym_prev;
  8943. ExprTokenType *fwd_infix, *this_infix = infix;
  8944. int functions_on_stack = 0;
  8945. for (;;) // While SYM_BEGIN is still on the stack, continue iterating.
  8946. {
  8947. ExprTokenType *&this_postfix = postfix[postfix_count]; // Resolve early, especially for use by "goto". Reduces code size a bit, though it doesn't measurably help performance.
  8948. infix_symbol = this_infix->symbol; //
  8949. stack_symbol = stack[stack_count - 1]->symbol; // Frequently used, so resolve only once to help performance.
  8950. // Put operands into the postfix array immediately, then move on to the next infix item:
  8951. if (IS_OPERAND(infix_symbol)) // At this stage, operands consist of only SYM_OPERAND and SYM_STRING.
  8952. {
  8953. if (infix_symbol == SYM_DYNAMIC && SYM_DYNAMIC_IS_VAR_NORMAL_OR_CLIP(this_infix)) // Ordered for short-circuit performance.
  8954. {
  8955. // v1.0.46.01: If an environment variable is being used as an lvalue -- regardless
  8956. // of whether that variable is blank in the environment -- treat it as a normal
  8957. // variable instead. This is because most people would want that, and also because
  8958. // it's tranditional not to directly support assignments to environment variables
  8959. // (only EnvSet can do that, mostly for code simplicity). In addition, things like
  8960. // EnvVar.="string" and EnvVar+=2 aren't supported due to obscurity/rarity (instead,
  8961. // such expressions treat EnvVar as blank). In light of all this, convert environment
  8962. // variables that are targets of ANY assignments into normal variables so that they
  8963. // can be seen as a valid lvalues when the time comes to do the assignment.
  8964. // IMPORTANT: VAR_CLIPBOARD is made into SYM_VAR here, but only for assignments.
  8965. // This allows built-in functions and other places in the code to treat SYM_VAR
  8966. // as though it's always VAR_NORMAL, which reduces code size and improves maintainability.
  8967. sym_prev = this_infix[1].symbol; // Resolve to help macro's code size and performance.
  8968. if (IS_ASSIGNMENT_OR_POST_OP(sym_prev) // Post-op must be checked for VAR_CLIPBOARD (by contrast, it seems unnecessary to check it for others; see comments below).
  8969. || stack_symbol == SYM_PRE_INCREMENT || stack_symbol == SYM_PRE_DECREMENT) // Stack *not* infix.
  8970. this_infix->symbol = SYM_VAR; // Convert clipboard or environment variable into SYM_VAR.
  8971. // POST-INC/DEC: It seems unnecessary to check for these except for VAR_CLIPBOARD because
  8972. // those assignments (and indeed any assignment other than .= and :=) will have no effect
  8973. // on a ON A SYM_DYNAMIC environment variable. This is because by definition, such
  8974. // variables have an empty Var::Contents(), and AutoHotkey v1 does not allow
  8975. // math operations on blank variables. Thus, the result of doing a math-assignment
  8976. // operation on a blank lvalue is almost the same as doing it on an invalid lvalue.
  8977. // The main difference is that with the exception of post-inc/dec, assignments
  8978. // wouldn't produce an lvalue unless we explicitly check for them all above.
  8979. // An lvalue should be produced so that the following features are consistent
  8980. // even for variables whose names happen to match those of environment variables:
  8981. // - Pass an assignment byref or takes its address; e.g. &(++x).
  8982. // - Cascading assigments; e.g. (++var) += 4 (rare to be sure).
  8983. // - Possibly other lvalue behaviors that rely on SYM_VAR being present.
  8984. // Above logic might not be perfect because it doesn't check for parens such as (var):=x,
  8985. // and possibly other obscure types of assignments. However, it seems adequate given
  8986. // the rarity of such things and also because env vars are being phased out (scripts can
  8987. // use #NoEnv to avoid all such issues).
  8988. }
  8989. this_postfix = this_infix++;
  8990. this_postfix->circuit_token = NULL; // Set default. It's only ever overridden after it's in the postfix array.
  8991. ++postfix_count;
  8992. continue; // Doing a goto to a hypothetical "standard_postfix_circuit_token" (in lieu of these last 3 lines) reduced performance and didn't help code size.
  8993. }
  8994. // Since above didn't "continue", the current infix symbol is not an operand, but an operator or other symbol.
  8995. switch(infix_symbol)
  8996. {
  8997. case SYM_CPAREN: // Listed first for performance. It occurs frequently while emptying the stack to search for the matching open-parenthesis.
  8998. if (stack_symbol == SYM_OPAREN) // See comments near the bottom of this case. The first open-paren on the stack must be the one that goes with this close-paren.
  8999. {
  9000. --stack_count; // Remove this open-paren from the stack, since it is now complete.
  9001. ++this_infix; // Since this pair of parentheses is done, move on to the next token in the infix expression.
  9002. // There should be no danger of stack underflow in the following because SYM_BEGIN always
  9003. // exists at the bottom of the stack:
  9004. if (stack[stack_count - 1]->symbol == SYM_FUNC) // i.e. topmost item on stack is SYM_FUNC.
  9005. {
  9006. --functions_on_stack;
  9007. goto standard_pop_into_postfix; // Within the postfix list, a function-call should always immediately follow its params.
  9008. }
  9009. }
  9010. else if (stack_symbol == SYM_BEGIN) // This can happen with bad expressions like "Var := 1 ? (:) :" even though theoretically it should mean that paren is closed without having been opened (currently impossible due to load-time balancing).
  9011. return LineError(ERR_MISSING_OPEN_PAREN); // Since this error string is used in other places, compiler string pooling should result in little extra memory needed for this line.
  9012. else // This stack item is an operator.
  9013. {
  9014. goto standard_pop_into_postfix;
  9015. // By not incrementing i, the loop will continue to encounter SYM_CPAREN and thus
  9016. // continue to pop things off the stack until the corresponding OPAREN is reached.
  9017. }
  9018. break;
  9019. case SYM_FUNC:
  9020. ++functions_on_stack; // This technique performs well but prevents multi-statements from being nested inside function calls (seems too obscure to worry about); e.g. fn((x:=5, y+=3), 2)
  9021. STACK_PUSH(this_infix++);
  9022. // NOW FALL INTO THE OPEN-PAREN BELOW because load-time validation has ensured that each SYM_FUNC
  9023. // is followed by a '('.
  9024. // ABOVE CASE FALLS INTO BELOW.
  9025. case SYM_OPAREN:
  9026. // Open-parentheses always go on the stack to await their matching close-parentheses.
  9027. STACK_PUSH(this_infix++);
  9028. break;
  9029. case SYM_IFF_ELSE: // i.e. this infix symbol is ':'.
  9030. if (stack_symbol == SYM_BEGIN) // An ELSE with no matching IF/THEN.
  9031. return L