本帖最后由 老刘1号 于 2023-9-25 00:08 编辑
这种问题靠猜也没用
把我压箱底的NT4系统泄露源代码翻出来- int SetWork(n)
- struct cmdnode *n ;
- {
- TCHAR *tas ; /* Tokenized argument string */
- TCHAR *wptr ; /* Work pointer */
- int i ; /* Work variable */
-
- //
- // If extensions are enabled, things are different
- //
- if (fEnableExtensions) {
- tas = n->argptr;
- //
- // Find first non-blank argument.
- //
- if (tas != NULL)
- while (*tas && *tas <= SPACE)
- tas += 1;
-
- //
- // No arguments, same as old behavior. Display current
- // set of environment variables.
- //
- if (!tas || !*tas)
- return(DisplayEnv()) ;
-
- //
- // See if /A switch given. If so, let arithmetic
- // expression evaluator do the work.
- //
- if (!_tcsnicmp(tas, SetArithStr, 2))
- return SetArithWork(tas+2);
-
- //
- // See if first argument is quoted. If so, strip off
- // leading quote, spaces and trailing quote.
- //
- if (*tas == QUOTE) {
- tas += 1;
- while (*tas && *tas <= SPACE)
- tas += 1;
- wptr = _tcsrchr(tas, QUOTE);
- if (wptr)
- *wptr = NULLC;
- }
-
- //
- // Find the equal sign in the argument.
- //
- wptr = _tcschr(tas, EQ);
-
- //
- // If no equal sign, then assume argument is variable name
- // and user wants to see its value. Display it.
- //
- if (!wptr)
- return DisplayEnvVariable(tas);
-
- //
- // Found the equal sign, so left of equal sign is variable name
- // and right of equal sign is value. Dont allow user to set
- // a variable name that begins with an equal sign, since those
- // are reserved for drive current directories.
- //
- *wptr++ = NULLC;
- if (*wptr == EQ) {
- PutStdErr(MSG_BAD_SYNTAX, NOARGS);
- return(FAILURE) ;
- }
-
- return(SetEnvVar(tas, wptr, &CmdEnv)) ;
- }
-
- tas = TokStr(n->argptr, ONEQSTR, TS_WSPACE|TS_SDTOKENS) ;
- if (!*tas)
- return(DisplayEnv()) ;
-
- else {
- for (wptr = tas, i = 0 ; *wptr ; wptr += mystrlen(wptr)+1, i++)
- ;
- /* If too many parameters were given, the second parameter */
- /* wasn't an equal sign, or they didn't specify a string */
- /* return an error message. */
- if ( i > 3 || *(wptr = tas+mystrlen(tas)+1) != EQ ||
- !mystrlen(mystrcpy(tas, stripit(tas))) ) {
- /* M013 */ PutStdErr(MSG_BAD_SYNTAX, NOARGS);
- return(FAILURE) ;
-
- } else {
- return(SetEnvVar(tas, wptr+2, &CmdEnv)) ;
- }
- } ;
- }
复制代码
- /*** SetArithWork - set environment variable to value of arithmetic expression
- *
- * Purpose:
- * Set environment variable to value of arithmetic expression
- *
- * int SetArithWork(TCHAR *tas)
- *
- * Args:
- * tas - pointer to null terminated string of the form:
- *
- * VARNAME=expression
- *
- * Returns:
- * If valid expression, return SUCCESS otherwise FAILURE.
- *
- */
-
- int SetArithWork(TCHAR *tas)
- {
- TCHAR c, szResult[ MAX_PATH ];
- TCHAR *szOperator;
- TCHAR *wptr;
- DWORD i;
- BOOLEAN bUnaryOpPossible;
- int rc;
-
-
- //
- // If no input, declare an error
- //
- if (!tas || !tas) {
- PutStdErr(MSG_BAD_SYNTAX, NOARGS);
- return(FAILURE) ;
- }
-
- //
- // Now evaluate the expression. Syntax accepted:
- //
- // <expr>: '(' <expr> ')'
- // | <unary-op> <expr>
- // | <expr> <binary-op> <expr>
- // | <variable>
- // | <number>
- //
- // <unary-op>: '+' | '-' |
- // '~' | '!'
- //
- // <binary-op>: '+' | '-' | '*' | '/' | '%'
- // '|' | '&' | '^' | '=' | ','
- //
- // <number>: C-syntax (e.g. 16 or 0x10)
- // <variable>: Any environment variable. Dont need surround with % to get value
- //
- // Operators have same meaning and precedence as ANSI C. All arithmetic is
- // fixed, 32 bit arithmetic. No floating point.
- //
-
- //
- // Poor man's parser/evaluator with operand and operator stack.
- //
- iOperand = 0;
- iOperator = 0;
- bUnaryOpPossible = TRUE;
- rc = SUCCESS;
- do {
- //
- // Look at next non blank character
- //
- c = *tas;
- if (c <= SPACE || c == QUOTE) {
- if (*tas)
- tas += 1;
- }
- else
- if (_istdigit(c)) {
- //
- // Digit, must be numeric operand. Push it on operand stack
- //
- lOperands[ iOperand ].Value = _tcstol(tas, &tas, 0);
- lOperands[ iOperand ].Name = NULL;
- iOperand += 1;
-
- if (_istdigit(*tas) || _istalpha(*tas)) {
- rc = MSG_SET_A_INVALID_NUMBER;
- break;
- }
-
- //
- // Unary op not possible after a operand.
- //
- bUnaryOpPossible = FALSE;
- }
- else
- if (bUnaryOpPossible && (szOperator = _tcschr(szUnaryOps, c))) {
- //
- // If unary op possible and we have one, then push it
- // on the operator stack
- tas += 1;
- if (rc = DoArithOps( wUnaryOpCodes[szOperator - szUnaryOps] ))
- break;
- }
- else
- if (!bUnaryOpPossible && (szOperator = _tcschr(szOps, c))) {
- //
- // If we have a binary op, push it on the operator stack
- //
- tas += 1;
-
- if (c == L'<' || c == L'>') {
- if (*tas != c) {
- rc = MSG_SYNERR_GENL;
- break;
- }
- tas += 1;
- }
-
- if (*tas == EQ) {
- tas += 1;
- if (rc = DoArithOps( A_EQOP ))
- break;
-
- if (iOperand == 0) {
- rc = MSG_SET_A_MISSING_OPERAND;
- break;
- }
- lOperands[ iOperand ] = lOperands[ iOperand-1 ];
- iOperand += 1;
- }
-
- if (rc = DoArithOps( wOpCodes[szOperator - szOps] ))
- break;
-
- //
- // Unary op now possible.
- //
-
- if (c == RPOP) {
- bUnaryOpPossible = FALSE;
- }
- else {
- bUnaryOpPossible = TRUE;
- }
- }
- else
- if (!bUnaryOpPossible) {
- rc = MSG_SET_A_MISSING_OPERATOR;
- break;
- }
- else {
- //
- // Not a number or operator, must be a variable name. The
- // name must be terminated by a space or an operator.
- //
- wptr = tas;
- while (*tas &&
- *tas > SPACE &&
- !_tcschr(szUnaryOps, *tas) &&
- !_tcschr(szOps, *tas)
- )
- tas += 1;
-
- //
- // If no variable or variable too long, bail
- //
- if (wptr == tas) {
- rc = MSG_SET_A_MISSING_OPERAND;
- break;
- }
-
- lOperands[ iOperand ].Value = 0;
- lOperands[ iOperand ].Name = gmkstr((tas-wptr+1)*sizeof(TCHAR));
- if (lOperands[ iOperand ].Name == NULL) {
- rc = MSG_NO_MEMORY;
- break;
- }
-
- //
- // Have variable name. Push name on operand stack with a zero
- // value. Value will be fetch when this operand is popped from
- // operand stack.
- //
- _tcsncpy(lOperands[ iOperand ].Name, wptr, tas-wptr);
- lOperands[ iOperand ].Name[tas-wptr] = NULLC;
- iOperand += 1;
-
- //
- // Unary op not possible after a operand.
- //
- bUnaryOpPossible = FALSE;
- }
-
- } while (*tas);
-
- if (rc == SUCCESS) {
- //
- // Do any pending operators.
- //
- rc = DoArithOps( 0 );
-
- //
- // If operator stack non-empty or more than one value
- // on operand stack, then invalid expression
- //
- if (rc == SUCCESS && (iOperator || iOperand != 1)) {
- if (iOperator)
- rc = MSG_SET_A_MISMATCHED_PARENS;
- else
- rc = MSG_SET_A_MISSING_OPERAND;
- }
- }
-
- if (rc != SUCCESS)
- PutStdErr(rc, ONEARG, tas);
- else {
- //
- // Valid result, display if not in a batch script.
- //
- if (!CurBat)
- cmd_printf( TEXT("%d"), lOperands[ 0 ].Value ) ;
- }
-
- return rc;
- }
复制代码
- /*** DoArithOps - push operator on operator stack arithmetic expression
- *
- * Purpose:
- * Push an operator on the operator stack. Operator precedence handed here
- *
- * int DoArithOps(USHORT OpCode)
- *
- * Args:
- * OpCode - operator value. Precendence encoded in value, such that operators
- * with higher precedence are numerically larger
- *
- * Returns:
- * If valid expression, return SUCCESS otherwise FAILURE.
- *
- */
- int
- DoArithOps(
- USHORT OpCode
- )
- {
- USHORT op;
- LONG op1, op2, result;
- TCHAR szResult[ 32 ];
-
- //
- // Loop until we can push this operator onto the operator stack.
- // These means we have to pop off and any operators on the stack
- // that have a higher precedence than the new operator.
- //
- while (TRUE) {
- if (OpCode == A_ENDOP) {
- //
- // If new opcode is a right parenthesis, then all done if
- // the left parenthesis is on the top of the operator stack
- //
- if (iOperator != 0 && wOperators[iOperator-1] == A_BEGOP) {
- iOperator -= 1;
- OpCode = 0;
- break;
- }
-
- //
- // No left paren left, keep popping until we see it. Error
- // if nothing left to pop.
- //
- if (iOperator == 0)
- return MSG_SET_A_MISMATCHED_PARENS;
- }
- else
- if (OpCode == 0) {
- //
- // OpCode zero is end of expression. Pop everything off.
- //
- if (iOperator == 0)
- break;
- }
- else
- if (iOperator == 0 || OpCode > wOperators[iOperator-1] || OpCode == A_BEGOP) {
- //
- // Done if no more operators to process or
- // New operator has higher precedence than operator on top of stack
- // or new operator is a left parenthesis
- //
- break;
- }
-
- //
- // We need to pop and process (i.e. evaluate) the operator stack
- // If it is a two operand stack, then get the second argument from
- // the top of the operand stack. Done if not two operands on the
- // operand stack.
- //
- op = wOperators[--iOperator];
- if (op < A_NEGOP) {
- if (iOperand < 2)
- break;
- op2 = PopOperand();
- }
-
- //
- // Get the first operand from the top of the operand stack. Error
- // if not one there.
- //
- if (iOperand < 1)
- break;
- op1 = PopOperand();
-
-
- //
- // Evaluate the operator and push the result back on the operand stack
- //
- result = 0;
- switch( op ) {
- case A_LSHOP: result = op1 << op2; break;
- case A_RSHOP: result = op1 >> op2; break;
- case A_ADDOP: result = op1 + op2; break;
- case A_SUBOP: result = op1 - op2; break;
- case A_MULOP: result = op1 * op2; break;
- case A_DIVOP: if (op2 == 0) return MSG_SET_A_MISSING_OPERAND;
- result = op1 / op2; break;
- case A_MODOP: result = op1 % op2; break;
- case A_ANDOP: result = op1 & op2; break;
- case A_OROP: result = op1 | op2; break;
- case A_XOROP: result = op1 ^ op2; break;
- case A_NEGOP: result = - op1; break;
- case A_POSOP: result = + op1; break;
- case A_NOTOP: result = ~ op1; break;
- case A_SEPOP: result = op2; break;
- case A_EQOP: if (lOperands[iOperand].Name == NULL) return MSG_SET_A_BAD_ASSIGN;
- result = op2;
- //
- // Left handside has variable name, convert result
- // to text and store as value of variable.
- //
- _sntprintf( szResult, 32, TEXT("%d"), result ) ;
- if (SetEnvVar(lOperands[iOperand].Name, szResult, &CmdEnv) != SUCCESS)
- return GetLastError();
- break;
-
- default: break;
- }
-
- lOperands[iOperand].Value = result;
- lOperands[iOperand].Name = NULL;
- iOperand += 1;
- }
-
- //
- // If new operator code is not the end of the expression, push it onto the
- // operator stack.
- //
- if (OpCode != 0)
- wOperators[ iOperator++ ] = OpCode;
- return SUCCESS;
- }
复制代码
|