ReactOS Fundraising Campaign 2012
 
€ 4,410 / € 30,000

Information | Donate

Home | Info | Community | Development | myReactOS | Contact Us

  1. Home
  2. Community
  3. Development
  4. myReactOS
  5. Fundraiser 2012

  1. Main Page
  2. Alphabetical List
  3. Data Structures
  4. Directories
  5. File List
  6. Data Fields
  7. Globals
  8. Related Pages

ReactOS Development > Doxygen

set.c
Go to the documentation of this file.
00001 /*
00002  *  SET.C - set internal command.
00003  *
00004  *
00005  *  History:
00006  *
00007  *    06/14/97 (Tim Norman)
00008  *        changed static var in set() to a cmd_alloc'd space to pass to putenv.
00009  *        need to find a better way to do this, since it seems it is wasting
00010  *        memory when variables are redefined.
00011  *
00012  *    07/08/1998 (John P. Price)
00013  *        removed call to show_environment in set command.
00014  *        moved test for syntax before allocating memory in set command.
00015  *        misc clean up and optimization.
00016  *
00017  *    27-Jul-1998 (John P Price <linux-guru@gcfl.net>)
00018  *        added config.h include
00019  *
00020  *    28-Jul-1998 (John P Price <linux-guru@gcfl.net>)
00021  *        added set_env function to set env. variable without needing set command
00022  *
00023  *    09-Dec-1998 (Eric Kohl)
00024  *        Added help text ("/?").
00025  *
00026  *    24-Jan-1999 (Eric Kohl)
00027  *        Fixed Win32 environment handling.
00028  *        Unicode and redirection safe!
00029  *
00030  *    25-Feb-1999 (Eric Kohl)
00031  *        Fixed little bug.
00032  *
00033  *    30-Apr-2005 (Magnus Olsen) <magnus@greatlord.com>)
00034  *        Remove all hardcode string to En.rc
00035  */
00036 
00037 #include <precomp.h>
00038 
00039 #ifdef INCLUDE_CMD_SET
00040 
00041 
00042 /* initial size of environment variable buffer */
00043 #define ENV_BUFFER_SIZE  1024
00044 
00045 static BOOL
00046 seta_eval ( LPCTSTR expr );
00047 
00048 static LPCTSTR
00049 skip_ws ( LPCTSTR p )
00050 {
00051     while (*p && *p <= _T(' '))
00052         p++;
00053     return p;
00054 }
00055 
00056 /* Used to check for and handle:
00057  * SET "var=value", SET /P "var=prompt", and SET /P var="prompt" */
00058 static LPTSTR
00059 GetQuotedString(TCHAR *p)
00060 {
00061     TCHAR *end;
00062     if (*p == _T('"'))
00063     {
00064         p = (LPTSTR)skip_ws(p + 1);
00065         /* If a matching quote is found, truncate the string */
00066         end = _tcsrchr(p, _T('"'));
00067         if (end)
00068             *end = _T('\0');
00069     }
00070     return p;
00071 }
00072 
00073 INT cmd_set (LPTSTR param)
00074 {
00075     LPTSTR p;
00076     LPTSTR lpEnv;
00077     LPTSTR lpOutput;
00078 
00079     if ( !_tcsncmp (param, _T("/?"), 2) )
00080     {
00081         ConOutResPaging(TRUE,STRING_SET_HELP);
00082         return 0;
00083     }
00084 
00085     param = (LPTSTR)skip_ws(param);
00086 
00087     /* if no parameters, show the environment */
00088     if (param[0] == _T('\0'))
00089     {
00090         lpEnv = (LPTSTR)GetEnvironmentStrings ();
00091         if (lpEnv)
00092         {
00093             lpOutput = lpEnv;
00094             while (*lpOutput)
00095             {
00096                 if (*lpOutput != _T('='))
00097                     ConOutPuts(lpOutput);
00098                 lpOutput += _tcslen(lpOutput) + 1;
00099             }
00100             FreeEnvironmentStrings (lpEnv);
00101         }
00102 
00103         return 0;
00104     }
00105 
00106     /* the /A does *NOT* have to be followed by a whitespace */
00107     if ( !_tcsnicmp (param, _T("/A"), 2) )
00108     {
00109         BOOL Success;
00110         StripQuotes(param);
00111         Success = seta_eval ( skip_ws(param+2) );
00112         if(!Success)
00113         {
00114             /*might seem random but this is what windows xp does */
00115             nErrorLevel = 9165;
00116         }
00117         return !Success;
00118     }
00119 
00120     if (!_tcsnicmp(param, _T("/P"), 2))
00121     {
00122         TCHAR value[1023];
00123         param = GetQuotedString((LPTSTR)skip_ws(param + 2));
00124         p = _tcschr(param, _T('='));
00125         if (!p)
00126         {
00127             ConErrResPuts(STRING_SYNTAX_COMMAND_INCORRECT);
00128             nErrorLevel = 1;
00129             return 1;
00130         }
00131 
00132         *p++ = _T('\0');
00133         ConOutPrintf(_T("%s"), GetQuotedString(p));
00134         ConInString(value, 1023);
00135 
00136         if (!*value || !SetEnvironmentVariable(param, value))
00137         {
00138             nErrorLevel = 1;
00139             return 1;
00140         }
00141         return 0;
00142     }
00143 
00144     param = GetQuotedString(param);
00145 
00146     p = _tcschr (param, _T('='));
00147     if (p)
00148     {
00149         /* set or remove environment variable */
00150         if (p == param)
00151         {
00152             /* handle set =val case */
00153             ConErrResPuts(STRING_SYNTAX_COMMAND_INCORRECT);
00154             nErrorLevel = 1;
00155             return 1;
00156         }
00157 
00158         *p++ = _T('\0');
00159         if (!SetEnvironmentVariable(param, *p ? p : NULL))
00160         {
00161             nErrorLevel = 1;
00162             return 1;
00163         }
00164     }
00165     else
00166     {
00167         /* display all environment variable with the given prefix */
00168         BOOL bFound = FALSE;
00169 
00170         while (_istspace(*param) || *param == _T(',') || *param == _T(';'))
00171             param++;
00172 
00173         p = _tcsrchr(param, _T(' '));
00174         if (!p)
00175             p = param + _tcslen(param);
00176         *p = _T('\0');
00177 
00178         lpEnv = GetEnvironmentStrings();
00179         if (lpEnv)
00180         {
00181             lpOutput = lpEnv;
00182             while (*lpOutput)
00183             {
00184                 if (!_tcsnicmp(lpOutput, param, p - param))
00185                 {
00186                     ConOutPuts(lpOutput);
00187                     bFound = TRUE;
00188                 }
00189                 lpOutput += _tcslen(lpOutput) + 1;
00190             }
00191             FreeEnvironmentStrings(lpEnv);
00192         }
00193 
00194         if (!bFound)
00195         {
00196             ConErrResPrintf (STRING_PATH_ERROR, param);
00197             nErrorLevel = 1;
00198             return 1;
00199         }
00200     }
00201 
00202     return 0;
00203 }
00204 
00205 static INT
00206 ident_len ( LPCTSTR p )
00207 {
00208     LPCTSTR p2 = p;
00209     if ( __iscsymf(*p) )
00210     {
00211         ++p2;
00212         while ( __iscsym(*p2) )
00213             ++p2;
00214     }
00215     return (INT)(p2-p);
00216 }
00217 
00218 #define PARSE_IDENT(ident,identlen,p) \
00219     identlen = ident_len(p); \
00220     ident = (LPTSTR)alloca ( ( identlen + 1 ) * sizeof(TCHAR) ); \
00221     memmove ( ident, p, identlen * sizeof(TCHAR) ); \
00222     ident[identlen] = 0; \
00223     p += identlen;
00224 
00225 static BOOL
00226 seta_identval ( LPCTSTR ident, INT* result )
00227 {
00228     LPCTSTR identVal = GetEnvVarOrSpecial ( ident );
00229     if ( !identVal )
00230     {
00231         /* TODO FIXME - what to do upon failure? */
00232         *result = 0;
00233         return FALSE;
00234     }
00235     *result = _tcstol ( identVal, NULL, 0 );
00236     return TRUE;
00237 }
00238 
00239 static BOOL
00240 calc ( INT* lval, TCHAR op, INT rval )
00241 {
00242     switch ( op )
00243     {
00244     case '*':
00245         *lval *= rval;
00246         break;
00247     case '/':
00248         *lval /= rval;
00249         break;
00250     case '%':
00251         *lval %= rval;
00252         break;
00253     case '+':
00254         *lval += rval;
00255         break;
00256     case '-':
00257         *lval -= rval;
00258         break;
00259     case '&':
00260         *lval &= rval;
00261         break;
00262     case '^':
00263         *lval ^= rval;
00264         break;
00265     case '|':
00266         *lval |= rval;
00267         break;
00268     default:
00269         ConErrResPuts ( STRING_INVALID_OPERAND );
00270         return FALSE;
00271     }
00272     return TRUE;
00273 }
00274 
00275 static BOOL
00276 seta_stmt ( LPCTSTR* p_, INT* result );
00277 
00278 static BOOL
00279 seta_unaryTerm ( LPCTSTR* p_, INT* result )
00280 {
00281     LPCTSTR p = *p_;
00282     if ( *p == _T('(') )
00283     {
00284         INT rval;
00285         p = skip_ws ( p + 1 );
00286         if ( !seta_stmt ( &p, &rval ) )
00287             return FALSE;
00288         if ( *p++ != _T(')') )
00289         {
00290             ConErrResPuts ( STRING_EXPECTED_CLOSE_PAREN );
00291             return FALSE;
00292         }
00293         *result = rval;
00294     }
00295     else if ( isdigit(*p) )
00296     {
00297         *result = _tcstol ( p, (LPTSTR *)&p, 0 );
00298     }
00299     else if ( __iscsymf(*p) )
00300     {
00301         LPTSTR ident;
00302         INT identlen;
00303         PARSE_IDENT(ident,identlen,p);
00304         if ( !seta_identval ( ident, result ) )
00305             return FALSE;
00306     }
00307     else
00308     {
00309         ConErrResPuts ( STRING_EXPECTED_NUMBER_OR_VARIABLE );
00310         return FALSE;
00311     }
00312     *p_ = skip_ws ( p );
00313     return TRUE;
00314 }
00315 
00316 static BOOL
00317 seta_mulTerm ( LPCTSTR* p_, INT* result )
00318 {
00319     LPCTSTR p = *p_;
00320     TCHAR op = 0;
00321     INT rval;
00322     if ( _tcschr(_T("!~-"),*p) )
00323     {
00324         op = *p;
00325         p = skip_ws ( p + 1 );
00326     }
00327     if ( !seta_unaryTerm ( &p, &rval ) )
00328         return FALSE;
00329     switch ( op )
00330     {
00331     case '!':
00332         rval = !rval;
00333         break;
00334     case '~':
00335         rval = ~rval;
00336         break;
00337     case '-':
00338         rval = -rval;
00339         break;
00340     }
00341 
00342     *result = rval;
00343     *p_ = p;
00344     return TRUE;
00345 }
00346 
00347 static BOOL
00348 seta_ltorTerm ( LPCTSTR* p_, INT* result, LPCTSTR ops, BOOL (*subTerm)(LPCTSTR*,INT*) )
00349 {
00350     LPCTSTR p = *p_;
00351     INT lval;
00352     if ( !subTerm ( &p, &lval ) )
00353         return FALSE;
00354     while ( *p && _tcschr(ops,*p) )
00355     {
00356         INT rval;
00357         TCHAR op = *p;
00358 
00359         p = skip_ws ( p+1 );
00360 
00361         if ( !subTerm ( &p, &rval ) )
00362             return FALSE;
00363 
00364         if ( !calc ( &lval, op, rval ) )
00365             return FALSE;
00366     }
00367 
00368     *result = lval;
00369     *p_ = p;
00370     return TRUE;
00371 }
00372 
00373 static BOOL
00374 seta_addTerm ( LPCTSTR* p_, INT* result )
00375 {
00376     return seta_ltorTerm ( p_, result, _T("*/%"), seta_mulTerm );
00377 }
00378 
00379 static BOOL
00380 seta_logShiftTerm ( LPCTSTR* p_, INT* result )
00381 {
00382     return seta_ltorTerm ( p_, result, _T("+-"), seta_addTerm );
00383 }
00384 
00385 static BOOL
00386 seta_bitAndTerm ( LPCTSTR* p_, INT* result )
00387 {
00388     LPCTSTR p = *p_;
00389     INT lval;
00390     if ( !seta_logShiftTerm ( &p, &lval ) )
00391         return FALSE;
00392     while ( *p && _tcschr(_T("<>"),*p) && p[0] == p[1] )
00393     {
00394         INT rval;
00395         TCHAR op = *p;
00396 
00397         p = skip_ws ( p+2 );
00398 
00399         if ( !seta_logShiftTerm ( &p, &rval ) )
00400             return FALSE;
00401 
00402         switch ( op )
00403         {
00404         case '<':
00405             lval <<= rval;
00406             break;
00407         case '>':
00408             lval >>= rval;
00409             break;
00410         default:
00411             ConErrResPuts ( STRING_INVALID_OPERAND );
00412             return FALSE;
00413         }
00414     }
00415 
00416     *result = lval;
00417     *p_ = p;
00418     return TRUE;
00419 }
00420 
00421 static BOOL
00422 seta_bitExclOrTerm ( LPCTSTR* p_, INT* result )
00423 {
00424     return seta_ltorTerm ( p_, result, _T("&"), seta_bitAndTerm );
00425 }
00426 
00427 static BOOL
00428 seta_bitOrTerm ( LPCTSTR* p_, INT* result )
00429 {
00430     return seta_ltorTerm ( p_, result, _T("^"), seta_bitExclOrTerm );
00431 }
00432 
00433 static BOOL
00434 seta_expr ( LPCTSTR* p_, INT* result )
00435 {
00436     return seta_ltorTerm ( p_, result, _T("|"), seta_bitOrTerm );
00437 }
00438 
00439 static BOOL
00440 seta_assignment ( LPCTSTR* p_, INT* result )
00441 {
00442     LPCTSTR p = *p_;
00443     LPTSTR ident;
00444     TCHAR op = 0;
00445     INT identlen, exprval;
00446 
00447     PARSE_IDENT(ident,identlen,p);
00448     if ( identlen )
00449     {
00450         p = skip_ws(p);
00451         if ( *p == _T('=') )
00452             op = *p, p = skip_ws(p+1);
00453         else if ( _tcschr ( _T("*/%+-&^|"), *p ) && p[1] == _T('=') )
00454             op = *p, p = skip_ws(p+2);
00455         else if ( _tcschr ( _T("<>"), *p ) && *p == p[1] && p[2] == _T('=') )
00456             op = *p, p = skip_ws(p+3);
00457     }
00458 
00459     /* allow to chain multiple assignments, such as: a=b=1 */
00460     if ( ident && op )
00461     {
00462         INT identval;
00463         LPTSTR buf;
00464 
00465         if ( !seta_assignment ( &p, &exprval ) )
00466             return FALSE;
00467 
00468         if ( !seta_identval ( ident, &identval ) )
00469             identval = 0;
00470         switch ( op )
00471         {
00472         case '=':
00473             identval = exprval;
00474             break;
00475         case '<':
00476             identval <<= exprval;
00477             break;
00478         case '>':
00479             identval >>= exprval;
00480             break;
00481         default:
00482             if ( !calc ( &identval, op, exprval ) )
00483                 return FALSE;
00484         }
00485         buf = (LPTSTR)alloca ( 32 * sizeof(TCHAR) );
00486         _sntprintf ( buf, 32, _T("%i"), identval );
00487         SetEnvironmentVariable ( ident, buf ); // TODO FIXME - check return value
00488         exprval = identval;
00489     }
00490     else
00491     {
00492         /* restore p in case we found an ident but not an op */
00493         p = *p_;
00494         if ( !seta_expr ( &p, &exprval ) )
00495             return FALSE;
00496     }
00497 
00498     *result = exprval;
00499     *p_ = p;
00500     return TRUE;
00501 }
00502 
00503 static BOOL
00504 seta_stmt ( LPCTSTR* p_, INT* result )
00505 {
00506     LPCTSTR p = *p_;
00507     INT rval;
00508 
00509     if ( !seta_assignment ( &p, &rval ) )
00510         return FALSE;
00511     while ( *p == _T(',') )
00512     {
00513         p = skip_ws ( p+1 );
00514 
00515         if ( !seta_assignment ( &p, &rval ) )
00516             return FALSE;
00517     }
00518 
00519     *result = rval;
00520     *p_ = p;
00521     return TRUE;
00522 }
00523 
00524 static BOOL
00525 seta_eval ( LPCTSTR p )
00526 {
00527     INT rval;
00528     if ( !*p )
00529     {
00530         ConErrResPuts ( STRING_SYNTAX_COMMAND_INCORRECT );
00531         return FALSE;
00532     }
00533     if ( !seta_stmt ( &p, &rval ) )
00534         return FALSE;
00535     if ( !bc )
00536         ConOutPrintf ( _T("%i"), rval );
00537     return TRUE;
00538 }
00539 
00540 #endif

Generated on Sat May 26 2012 04:17:07 for ReactOS by doxygen 1.7.6.1

ReactOS is a registered trademark or a trademark of ReactOS Foundation in the United States and other countries.