ReactOS  0.4.15-dev-1177-g6cb3b62
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 */
84  if (bEnableExtensions &&
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 
121 retry:
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 
190 NotFound:
192  ExitBatch();
193  return 1;
194 }
195 
196 /* EOF */
#define memmove(s1, s2, n)
Definition: mkisofs.h:881
DWORD mempos
Definition: batch.h:31
#define _tcsicmp
Definition: xmlstorage.h:205
#define TRUE
Definition: types.h:120
#define debugstr_aw
Definition: precomp.h:43
#define ARRAYSIZE(array)
Definition: filtermapper.c:47
VOID ConOutResPaging(BOOL StartPaging, UINT resID)
Definition: console.c:182
int32_t INT
Definition: typedefs.h:58
BOOL BatchGetString(LPTSTR lpBuffer, INT nBufferLength)
Definition: batch.c:526
CHAR * LPTSTR
Definition: xmlstorage.h:192
#define STRING_GOTO_HELP1
Definition: resource.h:135
#define FALSE
Definition: types.h:117
unsigned int BOOL
Definition: ntddk_ex.h:94
#define ConErrResPrintf(uID,...)
Definition: console.h:51
#define _tcsnicmp
Definition: xmlstorage.h:207
size_t __cdecl _tcslen(const _TCHAR *str)
Definition: tcslen.h:9
smooth NULL
Definition: ftsmooth.c:416
VOID ExitBatch(VOID)
Definition: batch.c:223
#define STRING_GOTO_ERROR2
Definition: resource.h:52
_TCHAR * _tcschr(const _TCHAR *s, _XINT c)
Definition: tcschr.h:4
TCHAR textline[BATCH_BUFFSIZE]
Definition: batch.c:76
#define _tcsstr
Definition: xmlstorage.h:199
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
unsigned long DWORD
Definition: ntddk_ex.h:95
BOOL bEnableExtensions
Definition: cmd.c:161
#define _istcntrl
Definition: tchar.h:739
#define STANDARD_SEPS
Definition: cmd.h:348
INT cmd_goto(LPTSTR param)
Definition: goto.c:36
uint8_t label[11]
Definition: fsck.fat.h:65
#define STRING_GOTO_ERROR1
Definition: resource.h:51
PARSED_COMMAND * current
Definition: batch.h:41
#define _istspace
Definition: tchar.h:1504
PBATCH_CONTEXT bc
Definition: batch.c:67
DWORD memsize
Definition: batch.h:30