ReactOS  0.4.15-dev-1203-g0e5a4d5
call.c
Go to the documentation of this file.
1 /*
2  * CALL.C - call internal batch command.
3  *
4  *
5  * History:
6  *
7  * 16 Jul 1998 (Hans B Pufal)
8  * started.
9  *
10  * 16 Jul 1998 (John P Price)
11  * Separated commands into individual files.
12  *
13  * 27-Jul-1998 (John P Price <linux-guru@gcfl.net>)
14  * added config.h include
15  *
16  * 04-Aug-1998 (Hans B Pufal)
17  * added lines to initialize for pointers (HBP004) This fixed the
18  * lock-up that happened sometimes when calling a batch file from
19  * another batch file.
20  *
21  * 07-Jan-1999 (Eric Kohl)
22  * Added help text ("call /?") and cleaned up.
23  *
24  * 20-Jan-1999 (Eric Kohl)
25  * Unicode and redirection safe!
26  *
27  * 02-Apr-2005 (Magnus Olsen <magnus@greatlord.com>)
28  * Remove all hardcoded strings in En.rc
29  */
30 
31 #include "precomp.h"
32 
33 /* Enable this define for "buggy" Windows' CMD CALL-command compatibility */
34 #define MSCMD_CALL_QUIRKS
35 
36 
37 /*
38  * Perform CALL command.
39  */
41 {
43  BOOL bOldIgnoreParserComments;
44 #ifndef MSCMD_CALL_QUIRKS
45  BOOL bOldHandleContinuations;
46 #else
47  SIZE_T nNumCarets;
48 #endif
49  PTSTR first;
50 
51  TRACE("cmd_call(\'%s\')\n", debugstr_aw(param));
52 
53  if (!_tcsncmp(param, _T("/?"), 2))
54  {
56  return 0;
57  }
58 
59  /* Fail if no command or label has been provided */
60  if (*param == _T('\0'))
61  return (nErrorLevel = 1);
62 
63  /* Ignore parser comments (starting with a colon) */
64  bOldIgnoreParserComments = bIgnoreParserComments;
66 
67 #ifndef MSCMD_CALL_QUIRKS
68  /* Disable parsing of escape carets */
69  bOldHandleContinuations = bHandleContinuations;
71  first = param;
72 #else
73  /*
74  * As the original escape carets have been dealt with during the first
75  * command parsing step, the remaining ones need to be doubled so that
76  * they can again survive the new parsing step done below.
77  * But do it the Windows' CMD "buggy" way: **all** carets are doubled,
78  * even those inside quotes. However, this causes carets inside quotes
79  * to remain doubled after the parsing step...
80  */
81 
82  /* Count all the carets */
83  nNumCarets = 0;
84  first = param;
85  while (first)
86  {
87  first = _tcschr(first, _T('^'));
88  if (first)
89  {
90  ++nNumCarets;
91  ++first;
92  }
93  }
94 
95  /* Re-allocate a large enough parameter string if needed */
96  if (nNumCarets > 0)
97  {
98  PTCHAR Src, Dest, End;
99 
100  // TODO: Improvement: Use the scratch TempBuf if the string is not too long.
101  first = cmd_alloc((_tcslen(param) + nNumCarets + 1) * sizeof(TCHAR));
102  if (!first)
103  {
104  WARN("Cannot allocate memory for new CALL parameter string!\n");
106  return (nErrorLevel = 1);
107  }
108 
109  /* Copy the parameter string and double the escape carets */
110  Src = param;
111  Dest = first;
112  while (*Src)
113  {
114  if (*Src != _T('^'))
115  {
116  /* Copy everything before the next caret (or the end of the string) */
117  End = _tcschr(Src, _T('^'));
118  if (!End)
119  End = Src + _tcslen(Src);
120  memcpy(Dest, Src, (End - Src) * sizeof(TCHAR));
121  Dest += End - Src;
122  Src = End;
123  continue;
124  }
125 
126  /* Copy the original caret and double it */
127  *Dest++ = *Src;
128  *Dest++ = *Src++;
129  }
130  *Dest = _T('\0');
131  }
132  else
133  {
134  first = param;
135  }
136 #endif
137 
138  /*
139  * Reparse the CALL parameter string as a command.
140  * Note that this will trigger a second round of %-variable substitutions.
141  */
143 
144  /* Restore the global parsing state */
145 #ifndef MSCMD_CALL_QUIRKS
146  bHandleContinuations = bOldHandleContinuations;
147 #endif
148  bIgnoreParserComments = bOldIgnoreParserComments;
149 
150  /*
151  * If no command is there, yet no error occurred, this means that
152  * a whitespace label was given. Do not consider this as a failure.
153  */
154  if (!Cmd && !bParseError)
155  {
156 #ifdef MSCMD_CALL_QUIRKS
157  if (first != param)
158  cmd_free(first);
159 #endif
160  return (nErrorLevel = 0);
161  }
162 
163  /* Reset bParseError so as to continue running afterwards */
164  bParseError = FALSE;
165 
166  /*
167  * Otherwise, if no command is there because a parse error occurred,
168  * or if this an unsupported command: not a standard one, including
169  * FOR and IF, fail and bail out.
170  */
171  if (!Cmd || (Cmd->Type == C_FOR) || (Cmd->Type == C_IF) ||
172  ((Cmd->Type != C_COMMAND) && (Cmd->Type != C_REM)))
173  {
174  // FIXME: Localize
175  ConErrPrintf(_T("%s was unexpected.\n"), first);
176 
177 #ifdef MSCMD_CALL_QUIRKS
178  if (first != param)
179  cmd_free(first);
180 #endif
181  if (Cmd) FreeCommand(Cmd);
182  return (nErrorLevel = 1);
183  }
184 
185 #ifdef MSCMD_CALL_QUIRKS
186  if (first != param)
187  cmd_free(first);
188 #endif
189 
190  first = Cmd->Command.First;
191  param = Cmd->Command.Rest;
192 
193  /* "CALL :label args ..." - Call a subroutine of the current batch file, only if extensions are enabled */
194  if (bEnableExtensions && (*first == _T(':')))
195  {
196  INT ret;
197 
198  /* A batch context must be present */
199  if (!bc)
200  {
201  // FIXME: Localize
202  ConErrPuts(_T("Invalid attempt to call batch label outside of batch script.\n"));
203  FreeCommand(Cmd);
204  return (nErrorLevel = 1);
205  }
206 
208  nErrorLevel = (ret != 0 ? ret : nErrorLevel);
209  }
210  else
211  {
213  }
214 
215  FreeCommand(Cmd);
216  return nErrorLevel;
217 }
218 
219 /* EOF */
INT nErrorLevel
Definition: cmd.c:158
TCHAR BatchFilePath[MAX_PATH]
Definition: batch.h:33
#define TRUE
Definition: types.h:120
Definition: cmd.h:361
const GLint * first
Definition: glext.h:5794
#define WARN(fmt,...)
Definition: debug.h:112
#define debugstr_aw
Definition: precomp.h:43
Definition: cmd.h:361
VOID ConOutResPaging(BOOL StartPaging, UINT resID)
Definition: console.c:182
PARSED_COMMAND * ParseCommand(IN PCTSTR Line)
Definition: parser.c:1461
int32_t INT
Definition: typedefs.h:58
CHAR * LPTSTR
Definition: xmlstorage.h:192
VOID FreeCommand(IN OUT PARSED_COMMAND *Cmd)
Definition: parser.c:527
Definition: cmd.h:353
#define FALSE
Definition: types.h:117
unsigned int BOOL
Definition: ntddk_ex.h:94
size_t __cdecl _tcslen(const _TCHAR *str)
Definition: tcslen.h:9
smooth NULL
Definition: ftsmooth.c:416
VOID error_out_of_memory(VOID)
Definition: error.c:138
CHAR * PTSTR
Definition: xmlstorage.h:191
_TCHAR * _tcschr(const _TCHAR *s, _XINT c)
Definition: tcschr.h:4
VOID ConErrPrintf(LPTSTR szFormat,...)
Definition: tee.c:36
char TCHAR
Definition: xmlstorage.h:189
#define _T(x)
Definition: vfdio.h:22
#define TRACE(s)
Definition: solgame.cpp:4
GLfloat param
Definition: glext.h:5796
VOID ConErrPuts(LPTSTR szText)
Definition: tee.c:59
BOOL bEnableExtensions
Definition: cmd.c:161
int ret
Definition: sacdrv.h:277
#define memcpy(s1, s2, n)
Definition: mkisofs.h:878
Definition: cmd.h:361
ULONG_PTR SIZE_T
Definition: typedefs.h:80
#define cmd_alloc(size)
Definition: cmddbg.h:29
INT cmd_call(LPTSTR param)
Definition: call.c:40
#define cmd_free(ptr)
Definition: cmddbg.h:31
BOOL bIgnoreParserComments
Definition: parser.c:96
static VOID DoCommand(PCONSOLE_STATE State, LPSTR line)
Definition: cmdcons.c:1082
BOOL bHandleContinuations
Definition: parser.c:97
#define STRING_CALL_HELP
Definition: resource.h:71
PBATCH_CONTEXT bc
Definition: batch.c:67
int _tcsncmp(const _TCHAR *s1, const _TCHAR *s2, size_t n)
Definition: tcsncmp.h:9
BOOL bParseError
Definition: parser.c:90
char * PTCHAR
Definition: ntbasedef.h:477