ReactOS 0.4.15-dev-7924-g5949c20
goto.c
Go to the documentation of this file.
1/*
2 * GOTO.C - goto internal batch command.
3 *
4 * History:
5 *
6 * 16 Jul 1998 (Hans B Pufal)
7 * started.
8 *
9 * 16 Jul 1998 (John P Price)
10 * Separated commands into individual files.
11 *
12 * 27-Jul-1998 (John P Price <linux-guru@gcfl.net>)
13 * added config.h include
14 *
15 * 28 Jul 1998 (Hans B Pufal) [HBP_003]
16 * Terminate label on first space character, use only first 8 chars of
17 * label string
18 *
19 * 24-Jan-1999 (Eric Kohl)
20 * Unicode and redirection safe!
21 *
22 * 27-Jan-1999 (Eric Kohl)
23 * Added help text ("/?").
24 *
25 * 28-Apr-2005 (Magnus Olsen <magnus@greatlord.com>)
26 * Remove all hardcoded strings in En.rc
27 */
28
29#include "precomp.h"
30
31/*
32 * Perform GOTO command.
33 *
34 * Only valid when a batch context is active.
35 */
37{
38 LPTSTR label, tmp;
39 DWORD dwCurrPos;
40 BOOL bRetry;
41
42 TRACE("cmd_goto(\'%s\')\n", debugstr_aw(param));
43
44 /*
45 * Keep the help message handling here too.
46 * This allows us to reproduce the Windows' CMD "bug"
47 * (from a batch script):
48 *
49 * SET label=/?
50 * CALL :%%label%%
51 *
52 * calls GOTO help, due to how CALL :label functionality
53 * is internally implemented.
54 *
55 * See https://stackoverflow.com/q/31987023/13530036
56 * for more details.
57 *
58 * Note that the choice of help parsing forbids
59 * any label containing '/?' in it.
60 */
61 if (_tcsstr(param, _T("/?")))
62 {
64 return 0;
65 }
66
67 /* If not in batch, fail */
68 if (bc == NULL)
69 return 1;
70
71 /* Fail if no label has been provided */
72 if (*param == _T('\0'))
73 {
75 ExitBatch();
76 return 1;
77 }
78
79 /* Strip leading whitespace */
80 while (_istspace(*param))
81 ++param;
82
83 /* Support jumping to the end of the file, only if extensions are enabled */
85 (_tcsnicmp(param, _T(":EOF"), 4) == 0) &&
86 (!param[4] || _istspace(param[4])))
87 {
88 /* Position at the end of the batch file */
89 bc->mempos = bc->memsize;
90
91 /* Do not process any more parts of a compound command */
92 bc->current = NULL;
93 return 0;
94 }
95
96 /* Skip the first colon or plus sign */
97 if (*param == _T(':') || *param == _T('+'))
98 ++param;
99 /* Terminate the label at the first delimiter character */
100 tmp = param;
101 while (!_istcntrl(*tmp) && !_istspace(*tmp) &&
102 !_tcschr(_T(":+"), *tmp) && !_tcschr(STANDARD_SEPS, *tmp) /* &&
103 !_tcschr(_T("&|<>"), *tmp) */)
104 {
105 ++tmp;
106 }
107 *tmp = _T('\0');
108
109 /* If we don't have any label, bail out */
110 if (!*param)
111 goto NotFound;
112
113 /*
114 * Search the next label starting our position, until the end of the file.
115 * If none has been found, restart at the beginning of the file, and continue
116 * until reaching back our old current position.
117 */
118 bRetry = FALSE;
119 dwCurrPos = bc->mempos;
120
121retry:
123 {
124 if (bRetry && (bc->mempos >= dwCurrPos))
125 break;
126
127#if 0
128 /* If this is not a label, continue searching */
129 if (!_tcschr(textline, _T(':')))
130 continue;
131#endif
132
133 label = textline;
134
135 /* A bug in Windows' CMD makes it always ignore the
136 * first character of the line, unless it's a colon. */
137 if (*label != _T(':'))
138 ++label;
139
140 /* Strip any leading whitespace */
141 while (_istspace(*label))
142 ++label;
143
144 /* If this is not a label, continue searching */
145 if (*label != _T(':'))
146 continue;
147
148 /* Skip the first colon or plus sign */
149#if 0
150 if (*label == _T(':') || *label == _T('+'))
151 ++label;
152#endif
153 ++label;
154 /* Strip any whitespace between the colon and the label */
155 while (_istspace(*label))
156 ++label;
157 /* Terminate the label at the first delimiter character */
158 tmp = label;
159 while (!_istcntrl(*tmp) && !_istspace(*tmp) &&
160 !_tcschr(_T(":+"), *tmp) && !_tcschr(STANDARD_SEPS, *tmp) &&
161 !_tcschr(_T("&|<>"), *tmp))
162 {
163 /* Support the escape caret */
164 if (*tmp == _T('^'))
165 {
166 /* Move the buffer back one character */
167 memmove(tmp, tmp + 1, (_tcslen(tmp + 1) + 1) * sizeof(TCHAR));
168 /* We will ignore the new character */
169 }
170
171 ++tmp;
172 }
173 *tmp = _T('\0');
174
175 /* Jump if the labels are identical */
176 if (_tcsicmp(label, param) == 0)
177 {
178 /* Do not process any more parts of a compound command */
179 bc->current = NULL;
180 return 0;
181 }
182 }
183 if (!bRetry && (bc->mempos >= bc->memsize))
184 {
185 bRetry = TRUE;
186 bc->mempos = 0;
187 goto retry;
188 }
189
190NotFound:
192 ExitBatch();
193 return 1;
194}
195
196/* EOF */
PBATCH_CONTEXT bc
Definition: batch.c:67
TCHAR textline[BATCH_BUFFSIZE]
Definition: batch.c:76
VOID ExitBatch(VOID)
Definition: batch.c:222
BOOL BatchGetString(LPTSTR lpBuffer, INT nBufferLength)
Definition: batch.c:527
#define STANDARD_SEPS
Definition: cmd.h:348
VOID ConOutResPaging(BOOL StartPaging, UINT resID)
Definition: console.c:182
#define ConErrResPrintf(uID,...)
Definition: console.h:50
#define debugstr_aw
Definition: precomp.h:43
#define STRING_GOTO_ERROR2
Definition: resource.h:52
#define STRING_GOTO_ERROR1
Definition: resource.h:51
#define STRING_GOTO_HELP1
Definition: resource.h:135
#define NULL
Definition: types.h:112
#define TRUE
Definition: types.h:120
#define FALSE
Definition: types.h:117
#define ARRAYSIZE(array)
Definition: filtermapper.c:47
unsigned int BOOL
Definition: ntddk_ex.h:94
unsigned long DWORD
Definition: ntddk_ex.h:95
GLfloat param
Definition: glext.h:5796
INT cmd_goto(LPTSTR param)
Definition: goto.c:36
#define _istspace
Definition: tchar.h:1504
#define _istcntrl
Definition: tchar.h:739
#define _tcschr
Definition: tchar.h:1406
#define memmove(s1, s2, n)
Definition: mkisofs.h:881
static const WCHAR label[]
Definition: itemdlg.c:1546
BOOL bEnableExtensions
Definition: more.c:53
#define TRACE(s)
Definition: solgame.cpp:4
DWORD memsize
Definition: batch.h:30
PARSED_COMMAND * current
Definition: batch.h:41
DWORD mempos
Definition: batch.h:31
int32_t INT
Definition: typedefs.h:58
#define _T(x)
Definition: vfdio.h:22
char TCHAR
Definition: xmlstorage.h:189
#define _tcsnicmp
Definition: xmlstorage.h:207
CHAR * LPTSTR
Definition: xmlstorage.h:192
#define _tcsstr
Definition: xmlstorage.h:199
#define _tcslen
Definition: xmlstorage.h:198
#define _tcsicmp
Definition: xmlstorage.h:205