2 * SET.C - set internal command.
7 * 06/14/97 (Tim Norman)
8 * changed static var in set() to a malloc'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 <ekohl@abo.rhein-zeitung.de>)
24 * Added help text ("/?").
26 * 24-Jan-1999 (Eric Kohl <ekohl@abo.rhein-zeitung.de>)
27 * Fixed Win32 environment handling.
28 * Unicode and redirection safe!
30 * 25-Feb-1999 (Eric Kohl <ekohl@abo.rhein-zeitung.de>)
33 * 30-Apr-2005 (Magnus Olsen) <magnus@greatlord.com>)
34 * Remove all hardcode string to En.rc
42 #ifdef INCLUDE_CMD_SET
45 /* initial size of environment variable buffer */
46 #define ENV_BUFFER_SIZE 1024
49 seta_eval ( LPCTSTR expr
);
54 return p
+ _tcsspn ( p
, _T(" \t") );
57 INT
cmd_set (LPTSTR cmd
, LPTSTR param
)
59 TCHAR szMsg
[RC_STRING_MAX_SIZE
];
63 if ( !_tcsncmp (param
, _T("/?"), 2) )
65 ConOutResPaging(TRUE
,STRING_SET_HELP
);
70 if ( param
[0] ) for ( i
= 0; param
[i
+1]; i
++ )
72 if ( param
[i
] == '^' && strchr("<|>&^",param
[i
+1]) )
74 memmove ( ¶m
[i
], ¶m
[i
+1], _tcslen(¶m
[i
]) * sizeof(TCHAR
) );
79 /* if no parameters, show the environment */
80 if (param
[0] == _T('\0'))
86 lpEnv
= (LPTSTR
)GetEnvironmentStrings ();
92 len
= _tcslen(lpOutput
);
95 if (*lpOutput
!= _T('='))
96 ConOutPuts (lpOutput
);
97 lpOutput
+= (len
+ 1);
100 FreeEnvironmentStrings (lpEnv
);
106 if ( !_tcsnicmp (param
, _T("/A"), 2) )
108 // TODO FIXME - what are we supposed to return?
109 return seta_eval ( skip_ws(param
+2) );
112 p
= _tcschr (param
, _T('='));
115 /* set or remove environment variable */
122 SetEnvironmentVariable (param
, p
);
126 /* display environment variable */
130 pszBuffer
= (LPTSTR
)malloc (ENV_BUFFER_SIZE
* sizeof(TCHAR
));
131 dwBuffer
= GetEnvironmentVariable (param
, pszBuffer
, ENV_BUFFER_SIZE
);
134 LoadString(CMD_ModuleHandle
, STRING_PATH_ERROR
, szMsg
, RC_STRING_MAX_SIZE
);
135 ConErrPrintf (szMsg
, param
);
138 else if (dwBuffer
> ENV_BUFFER_SIZE
)
140 pszBuffer
= (LPTSTR
)realloc (pszBuffer
, dwBuffer
* sizeof (TCHAR
));
141 GetEnvironmentVariable (param
, pszBuffer
, dwBuffer
);
143 ConOutPrintf (_T("%s\n"), pszBuffer
);
154 ident_len ( LPCTSTR p
)
160 while ( __iscsym(*p2
) )
166 #define PARSE_IDENT(ident,identlen,p) \
167 identlen = ident_len(p); \
168 ident = (LPTSTR)alloca ( ( identlen + 1 ) * sizeof(TCHAR) ); \
169 memmove ( ident, p, identlen * sizeof(TCHAR) ); \
170 ident[identlen] = 0; \
174 seta_identval ( LPCTSTR ident
, INT
* result
)
176 // get size of buffer for env var
178 DWORD dwBuffer
= GetEnvironmentVariable ( ident
, NULL
, 0 );
179 // if GetEnvironmentVariable() fails, it returns 0
182 // TODO FIXME - is it correct to report a value of 0 for non-existant variables?
186 buf
= (LPTSTR
)alloca ( dwBuffer
* sizeof(TCHAR
) );
189 // TODO FIXME - is it correct to report 0 when report resources low... should we error somehow?
193 GetEnvironmentVariable ( ident
, buf
, dwBuffer
);
194 *result
= _ttoi ( buf
);
199 calc ( INT
* lval
, TCHAR op
, INT rval
)
228 ConErrResPuts ( STRING_INVALID_OPERAND
);
235 seta_stmt ( LPCTSTR
* p_
, INT
* result
);
238 seta_unaryTerm ( LPCTSTR
* p_
, INT
* result
)
244 p
= skip_ws ( p
+ 1 );
245 if ( !seta_stmt ( &p
, &rval
) )
249 ConErrResPuts ( STRING_EXPECTED_CLOSE_PAREN
);
253 p
= skip_ws ( p
+ 1 );
255 else if ( isdigit(*p
) )
257 *result
= _ttoi ( p
);
258 p
= skip_ws ( p
+ _tcsspn ( p
, _T("1234567890") ) );
260 else if ( __iscsymf(*p
) )
264 PARSE_IDENT(ident
,identlen
,p
);
265 if ( !seta_identval ( ident
, result
) )
270 ConErrResPuts ( STRING_EXPECTED_NUMBER_OR_VARIABLE
);
278 seta_mulTerm ( LPCTSTR
* p_
, INT
* result
)
283 if ( _tcschr(_T("!~-"),*p
) )
286 p
= skip_ws ( p
+ 1 );
288 if ( !seta_unaryTerm ( &p
, &rval
) )
309 seta_ltorTerm ( LPCTSTR
* p_
, INT
* result
, LPCTSTR ops
, BOOL (*subTerm
)(LPCTSTR
*,INT
*) )
313 if ( !subTerm ( &p
, &lval
) )
315 while ( *p
&& _tcschr(ops
,*p
) )
322 if ( !subTerm ( &p
, &rval
) )
325 if ( !calc ( &lval
, op
, rval
) )
335 seta_addTerm ( LPCTSTR
* p_
, INT
* result
)
337 return seta_ltorTerm ( p_
, result
, _T("*/%"), seta_mulTerm
);
341 seta_logShiftTerm ( LPCTSTR
* p_
, INT
* result
)
343 return seta_ltorTerm ( p_
, result
, _T("+-"), seta_addTerm
);
347 seta_bitAndTerm ( LPCTSTR
* p_
, INT
* result
)
351 if ( !seta_logShiftTerm ( &p
, &lval
) )
353 while ( *p
&& _tcschr(_T("<>"),*p
) && p
[0] == p
[1] )
360 if ( !seta_logShiftTerm ( &p
, &rval
) )
372 ConErrResPuts ( STRING_INVALID_OPERAND
);
383 seta_bitExclOrTerm ( LPCTSTR
* p_
, INT
* result
)
385 return seta_ltorTerm ( p_
, result
, _T("&"), seta_bitAndTerm
);
389 seta_bitOrTerm ( LPCTSTR
* p_
, INT
* result
)
391 return seta_ltorTerm ( p_
, result
, _T("^"), seta_bitExclOrTerm
);
395 seta_expr ( LPCTSTR
* p_
, INT
* result
)
397 return seta_ltorTerm ( p_
, result
, _T("|"), seta_bitOrTerm
);
401 seta_assignment ( LPCTSTR
* p_
, INT
* result
)
406 INT identlen
, exprval
;
408 PARSE_IDENT(ident
,identlen
,p
);
412 op
= *p
, p
= skip_ws(p
+1);
413 else if ( _tcschr ( _T("*/%+-&^|"), *p
) && p
[1] == _T('=') )
414 op
= *p
, p
= skip_ws(p
+2);
415 else if ( _tcschr ( _T("<>"), *p
) && *p
== p
[1] && p
[2] == _T('=') )
416 op
= *p
, p
= skip_ws(p
+3);
419 /* allow to chain multiple assignments, such as: a=b=1 */
425 if ( !seta_assignment ( &p
, &exprval
) )
428 if ( !seta_identval ( ident
, &identval
) )
436 identval
<<= exprval
;
439 identval
>>= exprval
;
442 if ( !calc ( &identval
, op
, exprval
) )
445 buf
= (LPTSTR
)alloca ( 32 * sizeof(TCHAR
) );
446 _sntprintf ( buf
, 32, _T("%i"), identval
);
447 SetEnvironmentVariable ( ident
, buf
); // TODO FIXME - check return value
452 /* restore p in case we found an ident but not an op */
454 if ( !seta_expr ( &p
, &exprval
) )
464 seta_stmt ( LPCTSTR
* p_
, INT
* result
)
469 if ( !seta_assignment ( &p
, &rval
) )
471 while ( *p
== _T(',') )
475 if ( !seta_assignment ( &p
, &rval
) )
485 seta_eval ( LPCTSTR p
)
490 ConErrResPuts ( STRING_SYNTAX_COMMAND_INCORRECT
);
493 if ( !seta_stmt ( &p
, &rval
) )
495 ConOutPrintf ( _T("%i\n"), rval
);