7c9d7f0946b94d0ba209c38b0b54625fe4a85269
[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
26 #include "config.h"
27
28 #include <windows.h>
29 #include <tchar.h>
30 #include <string.h>
31 #include <stdlib.h>
32 #include <ctype.h>
33
34 #include "cmd.h"
35 #include "batch.h"
36
37
38 /*
39 * Perform FOR command.
40 *
41 * First check syntax is correct : FOR %v IN ( <list> ) DO <command>
42 * v must be alphabetic, <command> must not be empty.
43 *
44 * If all is correct build a new bcontext structure which preserves
45 * the necessary information so that readbatchline can expand
46 * each the command prototype for each list element.
47 *
48 * You might look on a FOR as being a called batch file with one line
49 * per list element.
50 */
51
52 INT cmd_for (LPTSTR cmd, LPTSTR param)
53 {
54 LPBATCH_CONTEXT lpNew;
55 LPTSTR pp;
56 TCHAR var;
57
58 #ifdef _DEBUG
59 DebugPrintf ("cmd_for (\'%s\', \'%s\'\n", cmd, param);
60 #endif
61
62 if (!_tcsncmp (param, _T("/?"), 2))
63 {
64 ConOutPuts (_T("Runs a specified command for each file in a set of files\n"
65 "\n"
66 "FOR %variable IN (set) DO command [parameters]\n"
67 "\n"
68 " %variable Specifies a replaceable parameter.\n"
69 " (set) Specifies a set of one or more files. Wildcards may be used.\n"
70 " command Specifies the command to carry out for each file.\n"
71 " parameters Specifies parameters or switches for the specified command.\n"
72 "\n"
73 "To user the FOR comamnd in a batch program, specify %%variable instead of\n"
74 "%variable."));
75 return 0;
76 }
77
78 /* Check that first element is % then an alpha char followed by space */
79 if ((*param != _T('%')) || !_istalpha (*(param + 1)) || !_istspace (*(param + 2)))
80 {
81 error_syntax (_T("bad variable specification."));
82 return 1;
83 }
84
85 param++;
86 var = *param++; /* Save FOR var name */
87
88 while (_istspace (*param))
89 param++;
90
91 /* Check next element is 'IN' */
92 if ((_tcsnicmp (param, _T("in"), 2) != 0) || !_istspace (*(param + 2)))
93 {
94 error_syntax (_T("'in' missing in for statement."));
95 return 1;
96 }
97
98 param += 2;
99 while (_istspace (*param))
100 param++;
101
102 /* Folowed by a '(', find also matching ')' */
103 if ((*param != _T('(')) || (NULL == (pp = _tcsrchr (param, _T(')')))))
104 {
105 error_syntax (_T("no brackets found."));
106 return 1;
107 }
108
109 *pp++ = _T('\0');
110 param++; /* param now points at null terminated list */
111
112 while (_istspace (*pp))
113 pp++;
114
115 /* Check DO follows */
116 if ((_tcsnicmp (pp, _T("do"), 2) != 0) || !_istspace (*(pp + 2)))
117 {
118 error_syntax (_T("'do' missing."));
119 return 1;
120 }
121
122 pp += 2;
123 while (_istspace (*pp))
124 pp++;
125
126 /* Check that command tail is not empty */
127 if (*pp == _T('\0'))
128 {
129 error_syntax (_T("no command after 'do'."));
130 return 1;
131 }
132
133 /* OK all is correct, build a bcontext.... */
134 lpNew = (LPBATCH_CONTEXT)malloc (sizeof (BATCH_CONTEXT));
135
136 lpNew->prev = bc;
137 bc = lpNew;
138
139 bc->hBatchFile = INVALID_HANDLE_VALUE;
140 bc->ffind = NULL;
141 bc->params = BatchParams (_T(""), param); /* Split out list */
142 bc->shiftlevel = 0;
143 bc->forvar = var;
144 bc->forproto = _tcsdup (pp);
145
146 return 0;
147 }
148
149 /* EOF */