2 * SET.C - set internal command.
7 * 06/14/97 (Tim Norman)
8 * changed static var in set() to a cmd_alloc'd space to pass to putenv.
9 * need to find a better way to do this, since it seems it is wasting
10 * memory when variables are redefined.
12 * 07/08/1998 (John P. Price)
13 * removed call to show_environment in set command.
14 * moved test for syntax before allocating memory in set command.
15 * misc clean up and optimization.
17 * 27-Jul-1998 (John P Price <linux-guru@gcfl.net>)
18 * added config.h include
20 * 28-Jul-1998 (John P Price <linux-guru@gcfl.net>)
21 * added set_env function to set env. variable without needing set command
23 * 09-Dec-1998 (Eric Kohl)
24 * Added help text ("/?").
26 * 24-Jan-1999 (Eric Kohl)
27 * Fixed Win32 environment handling.
28 * Unicode and redirection safe!
30 * 25-Feb-1999 (Eric Kohl)
33 * 30-Apr-2005 (Magnus Olsen) <magnus@greatlord.com>)
34 * Remove all hardcode string to En.rc
39 #ifdef INCLUDE_CMD_SET
42 /* initial size of environment variable buffer */
43 #define ENV_BUFFER_SIZE 1024
46 seta_eval ( LPCTSTR expr
);
51 return p
+ _tcsspn ( p
, _T(" \t") );
54 INT
cmd_set (LPTSTR cmd
, LPTSTR param
)
56 TCHAR szMsg
[RC_STRING_MAX_SIZE
];
60 if ( !_tcsncmp (param
, _T("/?"), 2) )
62 ConOutResPaging(TRUE
,STRING_SET_HELP
);
67 if ( param
[0] ) for ( i
= 0; param
[i
+1]; i
++ )
69 if ( param
[i
] == _T('^') )
71 memmove ( ¶m
[i
], ¶m
[i
+1], _tcslen(¶m
[i
]) * sizeof(TCHAR
) );
75 /* if no parameters, show the environment */
76 if (param
[0] == _T('\0'))
82 lpEnv
= (LPTSTR
)GetEnvironmentStrings ();
88 len
= _tcslen(lpOutput
);
91 if (*lpOutput
!= _T('='))
92 ConOutPuts (lpOutput
);
93 lpOutput
+= (len
+ 1);
96 FreeEnvironmentStrings (lpEnv
);
102 /* the /A does *NOT* have to be followed by a whitespace */
103 if ( !_tcsnicmp (param
, _T("/A"), 2) )
105 BOOL Success
= seta_eval ( skip_ws(param
+2) );
108 /*might seem random but this is what windows xp does */
111 /* TODO FIXME - what are we supposed to return? */
115 if ( !_tcsnicmp (param
, _T("/"), 1) )
117 LoadString(CMD_ModuleHandle
, STRING_SYNTAX_COMMAND_INCORRECT
, szMsg
, RC_STRING_MAX_SIZE
);
118 ConErrPrintf (szMsg
, param
);
122 p
= _tcschr (param
, _T('='));
125 /* set or remove environment variable */
128 /* handle set =val case */
129 LoadString(CMD_ModuleHandle
, STRING_SYNTAX_COMMAND_INCORRECT
, szMsg
, RC_STRING_MAX_SIZE
);
130 ConErrPrintf (szMsg
, param
);
140 SetEnvironmentVariable (param
, p
);
144 /* display environment variable */
148 pszBuffer
= (LPTSTR
)cmd_alloc (ENV_BUFFER_SIZE
* sizeof(TCHAR
));
149 dwBuffer
= GetEnvironmentVariable (param
, pszBuffer
, ENV_BUFFER_SIZE
);
152 LoadString(CMD_ModuleHandle
, STRING_PATH_ERROR
, szMsg
, RC_STRING_MAX_SIZE
);
153 ConErrPrintf (szMsg
, param
);
156 else if (dwBuffer
> ENV_BUFFER_SIZE
)
158 pszBuffer
= (LPTSTR
)cmd_realloc (pszBuffer
, dwBuffer
* sizeof (TCHAR
));
159 GetEnvironmentVariable (param
, pszBuffer
, dwBuffer
);
161 ConOutPrintf (_T("%s\n"), pszBuffer
);
163 cmd_free (pszBuffer
);
172 ident_len ( LPCTSTR p
)
178 while ( __iscsym(*p2
) )
184 #define PARSE_IDENT(ident,identlen,p) \
185 identlen = ident_len(p); \
186 ident = (LPTSTR)alloca ( ( identlen + 1 ) * sizeof(TCHAR) ); \
187 memmove ( ident, p, identlen * sizeof(TCHAR) ); \
188 ident[identlen] = 0; \
192 seta_identval ( LPCTSTR ident
, INT
* result
)
194 LPCTSTR identVal
= GetEnvVarOrSpecial ( ident
);
197 /* TODO FIXME - what to do upon failure? */
201 *result
= _ttoi ( identVal
);
206 calc ( INT
* lval
, TCHAR op
, INT rval
)
235 ConErrResPuts ( STRING_INVALID_OPERAND
);
242 seta_stmt ( LPCTSTR
* p_
, INT
* result
);
245 seta_unaryTerm ( LPCTSTR
* p_
, INT
* result
)
251 p
= skip_ws ( p
+ 1 );
252 if ( !seta_stmt ( &p
, &rval
) )
256 ConErrResPuts ( STRING_EXPECTED_CLOSE_PAREN
);
260 p
= skip_ws ( p
+ 1 );
262 else if ( isdigit(*p
) )
264 *result
= _ttoi ( p
);
265 p
= skip_ws ( p
+ _tcsspn ( p
, _T("1234567890") ) );
267 else if ( __iscsymf(*p
) )
271 PARSE_IDENT(ident
,identlen
,p
);
272 if ( !seta_identval ( ident
, result
) )
277 ConErrResPuts ( STRING_EXPECTED_NUMBER_OR_VARIABLE
);
285 seta_mulTerm ( LPCTSTR
* p_
, INT
* result
)
290 if ( _tcschr(_T("!~-"),*p
) )
293 p
= skip_ws ( p
+ 1 );
295 if ( !seta_unaryTerm ( &p
, &rval
) )
316 seta_ltorTerm ( LPCTSTR
* p_
, INT
* result
, LPCTSTR ops
, BOOL (*subTerm
)(LPCTSTR
*,INT
*) )
320 if ( !subTerm ( &p
, &lval
) )
322 while ( *p
&& _tcschr(ops
,*p
) )
329 if ( !subTerm ( &p
, &rval
) )
332 if ( !calc ( &lval
, op
, rval
) )
342 seta_addTerm ( LPCTSTR
* p_
, INT
* result
)
344 return seta_ltorTerm ( p_
, result
, _T("*/%"), seta_mulTerm
);
348 seta_logShiftTerm ( LPCTSTR
* p_
, INT
* result
)
350 return seta_ltorTerm ( p_
, result
, _T("+-"), seta_addTerm
);
354 seta_bitAndTerm ( LPCTSTR
* p_
, INT
* result
)
358 if ( !seta_logShiftTerm ( &p
, &lval
) )
360 while ( *p
&& _tcschr(_T("<>"),*p
) && p
[0] == p
[1] )
367 if ( !seta_logShiftTerm ( &p
, &rval
) )
379 ConErrResPuts ( STRING_INVALID_OPERAND
);
390 seta_bitExclOrTerm ( LPCTSTR
* p_
, INT
* result
)
392 return seta_ltorTerm ( p_
, result
, _T("&"), seta_bitAndTerm
);
396 seta_bitOrTerm ( LPCTSTR
* p_
, INT
* result
)
398 return seta_ltorTerm ( p_
, result
, _T("^"), seta_bitExclOrTerm
);
402 seta_expr ( LPCTSTR
* p_
, INT
* result
)
404 return seta_ltorTerm ( p_
, result
, _T("|"), seta_bitOrTerm
);
408 seta_assignment ( LPCTSTR
* p_
, INT
* result
)
413 INT identlen
, exprval
;
415 PARSE_IDENT(ident
,identlen
,p
);
419 op
= *p
, p
= skip_ws(p
+1);
420 else if ( _tcschr ( _T("*/%+-&^|"), *p
) && p
[1] == _T('=') )
421 op
= *p
, p
= skip_ws(p
+2);
422 else if ( _tcschr ( _T("<>"), *p
) && *p
== p
[1] && p
[2] == _T('=') )
423 op
= *p
, p
= skip_ws(p
+3);
426 /* allow to chain multiple assignments, such as: a=b=1 */
432 if ( !seta_assignment ( &p
, &exprval
) )
435 if ( !seta_identval ( ident
, &identval
) )
443 identval
<<= exprval
;
446 identval
>>= exprval
;
449 if ( !calc ( &identval
, op
, exprval
) )
452 buf
= (LPTSTR
)alloca ( 32 * sizeof(TCHAR
) );
453 _sntprintf ( buf
, 32, _T("%i"), identval
);
454 SetEnvironmentVariable ( ident
, buf
); // TODO FIXME - check return value
459 /* restore p in case we found an ident but not an op */
461 if ( !seta_expr ( &p
, &exprval
) )
471 seta_stmt ( LPCTSTR
* p_
, INT
* result
)
476 if ( !seta_assignment ( &p
, &rval
) )
478 while ( *p
== _T(',') )
482 if ( !seta_assignment ( &p
, &rval
) )
492 seta_eval ( LPCTSTR p
)
497 ConErrResPuts ( STRING_SYNTAX_COMMAND_INCORRECT
);
500 if ( !seta_stmt ( &p
, &rval
) )
502 ConOutPrintf ( _T("%i"), rval
);