Various improvements by Carl Nettelblad.
[reactos.git] / rosapps / cmd / for.c
1 /*
2 * FOR.C - for 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 * Seperated commands into individual files.
12 *
13 * 19-Jul-1998 (Hans B Pufal)
14 * Implementation of FOR.
15 *
16 * 27-Jul-1998 (John P Price <linux-guru@gcfl.net>)
17 * Added config.h include.
18 *
19 * 20-Jan-1999 (Eric Kohl)
20 * Unicode and redirection safe!
21 *
22 * 01-Sep-1999 (Eric Kohl)
23 * Added help text.
24 *
25 * 23-Feb-2001 (Carl Nettelblad <cnettel@hem.passagen.se>)
26 * Implemented preservation of echo flag. Some other for related
27 * code in other files fixed, too.
28 */
29
30 #include "config.h"
31
32 #include <windows.h>
33 #include <tchar.h>
34 #include <string.h>
35 #include <stdlib.h>
36 #include <ctype.h>
37
38 #include "cmd.h"
39 #include "batch.h"
40
41
42 /*
43 * Perform FOR command.
44 *
45 * First check syntax is correct : FOR %v IN ( <list> ) DO <command>
46 * v must be alphabetic, <command> must not be empty.
47 *
48 * If all is correct build a new bcontext structure which preserves
49 * the necessary information so that readbatchline can expand
50 * each the command prototype for each list element.
51 *
52 * You might look on a FOR as being a called batch file with one line
53 * per list element.
54 */
55
56 INT cmd_for (LPTSTR cmd, LPTSTR param)
57 {
58 LPBATCH_CONTEXT lpNew;
59 LPTSTR pp;
60 TCHAR var;
61
62 #ifdef _DEBUG
63 DebugPrintf ("cmd_for (\'%s\', \'%s\'\n", cmd, param);
64 #endif
65
66 if (!_tcsncmp (param, _T("/?"), 2))
67 {
68 ConOutPuts (_T("Runs a specified command for each file in a set of files\n"
69 "\n"
70 "FOR %variable IN (set) DO command [parameters]\n"
71 "\n"
72 " %variable Specifies a replaceable parameter.\n"
73 " (set) Specifies a set of one or more files. Wildcards may be used.\n"
74 " command Specifies the command to carry out for each file.\n"
75 " parameters Specifies parameters or switches for the specified command.\n"
76 "\n"
77 "To user the FOR comamnd in a batch program, specify %%variable instead of\n"
78 "%variable."));
79 return 0;
80 }
81
82 /* Check that first element is % then an alpha char followed by space */
83 if ((*param != _T('%')) || !_istalpha (*(param + 1)) || !_istspace (*(param + 2)))
84 {
85 error_syntax (_T("bad variable specification."));
86 return 1;
87 }
88
89 param++;
90 var = *param++; /* Save FOR var name */
91
92 while (_istspace (*param))
93 param++;
94
95 /* Check next element is 'IN' */
96 if ((_tcsnicmp (param, _T("in"), 2) != 0) || !_istspace (*(param + 2)))
97 {
98 error_syntax (_T("'in' missing in for statement."));
99 return 1;
100 }
101
102 param += 2;
103 while (_istspace (*param))
104 param++;
105
106 /* Folowed by a '(', find also matching ')' */
107 if ((*param != _T('(')) || (NULL == (pp = _tcsrchr (param, _T(')')))))
108 {
109 error_syntax (_T("no brackets found."));
110 return 1;
111 }
112
113 *pp++ = _T('\0');
114 param++; /* param now points at null terminated list */
115
116 while (_istspace (*pp))
117 pp++;
118
119 /* Check DO follows */
120 if ((_tcsnicmp (pp, _T("do"), 2) != 0) || !_istspace (*(pp + 2)))
121 {
122 error_syntax (_T("'do' missing."));
123 return 1;
124 }
125
126 pp += 2;
127 while (_istspace (*pp))
128 pp++;
129
130 /* Check that command tail is not empty */
131 if (*pp == _T('\0'))
132 {
133 error_syntax (_T("no command after 'do'."));
134 return 1;
135 }
136
137 /* OK all is correct, build a bcontext.... */
138 lpNew = (LPBATCH_CONTEXT)malloc (sizeof (BATCH_CONTEXT));
139
140 lpNew->prev = bc;
141 bc = lpNew;
142
143 bc->hBatchFile = INVALID_HANDLE_VALUE;
144 bc->ffind = NULL;
145 bc->params = BatchParams (_T(""), param); /* Split out list */
146 bc->shiftlevel = 0;
147 bc->forvar = var;
148 bc->forproto = _tcsdup (pp);
149 if (bc->prev)
150 bc->bEcho = bc->prev->bEcho;
151 else
152 bc->bEcho = bEcho;
153
154 return 0;
155 }
156
157 /* EOF */