Something went wrong. Try again.
Reactos
Something went wrong. Try again.
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218/* * CALL.C - call internal batch command. * * * History: * * 16 Jul 1998 (Hans B Pufal) * started. * * 16 Jul 1998 (John P Price) * Separated commands into individual files. * * 27-Jul-1998 (John P Price <linux-guru@gcfl.net>) * added config.h include * * 04-Aug-1998 (Hans B Pufal) * added lines to initialize for pointers (HBP004) This fixed the * lock-up that happened sometimes when calling a batch file from * another batch file. * * 07-Jan-1999 (Eric Kohl) * Added help text ("call /?") and cleaned up. * * 20-Jan-1999 (Eric Kohl) * Unicode and redirection safe! * * 02-Apr-2005 (Magnus Olsen <magnus@greatlord.com>) * Remove all hardcoded strings in En.rc */
#include "precomp.h"
/* Enable this define for "buggy" Windows' CMD CALL-command compatibility */#define MSCMD_CALL_QUIRKS
/* * Perform CALL command. */INT cmd_call(LPTSTR param){ PARSED_COMMAND* Cmd = NULL; BOOL bOldIgnoreParserComments;#ifndef MSCMD_CALL_QUIRKS BOOL bOldHandleContinuations;#else SIZE_T nNumCarets;#endif PTSTR first;
TRACE("cmd_call(\'%s\')\n", debugstr_aw(param));
if (!_tcsncmp(param, _T("/?"), 2)) { ConOutResPaging(TRUE, STRING_CALL_HELP); return 0; }
/* Fail if no command or label has been provided */ if (*param == _T('\0')) return (nErrorLevel = 1);
/* Ignore parser comments (starting with a colon) */ bOldIgnoreParserComments = bIgnoreParserComments; bIgnoreParserComments = FALSE;
#ifndef MSCMD_CALL_QUIRKS /* Disable parsing of escape carets */ bOldHandleContinuations = bHandleContinuations; bHandleContinuations = FALSE; first = param;#else /* * As the original escape carets have been dealt with during the first * command parsing step, the remaining ones need to be doubled so that * they can again survive the new parsing step done below. * But do it the Windows' CMD "buggy" way: **all** carets are doubled, * even those inside quotes. However, this causes carets inside quotes * to remain doubled after the parsing step... */
/* Count all the carets */ nNumCarets = 0; first = param; while (first) { first = _tcschr(first, _T('^')); if (first) { ++nNumCarets; ++first; } }
/* Re-allocate a large enough parameter string if needed */ if (nNumCarets > 0) { PTCHAR Src, Dest, End;
// TODO: Improvement: Use the scratch TempBuf if the string is not too long. first = cmd_alloc((_tcslen(param) + nNumCarets + 1) * sizeof(TCHAR)); if (!first) { WARN("Cannot allocate memory for new CALL parameter string!\n"); error_out_of_memory(); return (nErrorLevel = 1); }
/* Copy the parameter string and double the escape carets */ Src = param; Dest = first; while (*Src) { if (*Src != _T('^')) { /* Copy everything before the next caret (or the end of the string) */ End = _tcschr(Src, _T('^')); if (!End) End = Src + _tcslen(Src); memcpy(Dest, Src, (End - Src) * sizeof(TCHAR)); Dest += End - Src; Src = End; continue; }
/* Copy the original caret and double it */ *Dest++ = *Src; *Dest++ = *Src++; } *Dest = _T('\0'); } else { first = param; }#endif
/* * Reparse the CALL parameter string as a command. * Note that this will trigger a second round of %-variable substitutions. */ Cmd = ParseCommand(first);
/* Restore the global parsing state */#ifndef MSCMD_CALL_QUIRKS bHandleContinuations = bOldHandleContinuations;#endif bIgnoreParserComments = bOldIgnoreParserComments;
/* * If no command is there, yet no error occurred, this means that * a whitespace label was given. Do not consider this as a failure. */ if (!Cmd && !bParseError) {#ifdef MSCMD_CALL_QUIRKS if (first != param) cmd_free(first);#endif return (nErrorLevel = 0); }
/* Reset bParseError so as to continue running afterwards */ bParseError = FALSE;
/* * Otherwise, if no command is there because a parse error occurred, * or if this an unsupported command: not a standard one, including * FOR and IF, fail and bail out. */ if (!Cmd || (Cmd->Type == C_FOR) || (Cmd->Type == C_IF) || ((Cmd->Type != C_COMMAND) && (Cmd->Type != C_REM))) { ConErrResPrintf(STRING_ERROR_UNEXPECTED, first);
#ifdef MSCMD_CALL_QUIRKS if (first != param) cmd_free(first);#endif if (Cmd) FreeCommand(Cmd); return (nErrorLevel = 1); }
#ifdef MSCMD_CALL_QUIRKS if (first != param) cmd_free(first);#endif
first = Cmd->Command.First; param = Cmd->Command.Rest;
/* "CALL :label args ..." - Call a subroutine of the current batch file, only if extensions are enabled */ if (bEnableExtensions && (*first == _T(':'))) { INT ret;
/* A batch context must be present */ if (!bc) { ConErrResPuts(STRING_ERROR_CALL_BAD_LABEL); FreeCommand(Cmd); return (nErrorLevel = 1); }
ret = Batch(bc->BatchFilePath, first, param, NULL); nErrorLevel = (ret != 0 ? ret : nErrorLevel); } else { nErrorLevel = DoCommand(first, param, NULL); }
FreeCommand(Cmd); return nErrorLevel;}
/* EOF */