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

kdb_expr.c
Go to the documentation of this file.
00001 /*
00002  *  ReactOS kernel
00003  *  Copyright (C) 2005 ReactOS Team
00004  *
00005  *  This program is free software; you can redistribute it and/or modify
00006  *  it under the terms of the GNU General Public License as published by
00007  *  the Free Software Foundation; either version 2 of the License, or
00008  *  (at your option) any later version.
00009  *
00010  *  This program is distributed in the hope that it will be useful,
00011  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
00012  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00013  *  GNU General Public License for more details.
00014  *
00015  *  You should have received a copy of the GNU General Public License along
00016  *  with this program; if not, write to the Free Software Foundation, Inc.,
00017  *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
00018  */
00019 /*
00020  * PROJECT:         ReactOS kernel
00021  * FILE:            ntoskrnl/dbg/kdb_expr.c
00022  * PURPOSE:         Kernel debugger expression evaluation
00023  * PROGRAMMER:      Gregor Anich (blight@blight.eu.org)
00024  * UPDATE HISTORY:
00025  *                  Created 15/01/2005
00026  */
00027 
00028 /* Note:
00029  *
00030  * The given expression is parsed and stored in reverse polish notation,
00031  * then it is evaluated and the result is returned.
00032  */
00033 
00034 /* INCLUDES ******************************************************************/
00035 
00036 #include <ntoskrnl.h>
00037 #define NDEBUG
00038 #include <debug.h>
00039 
00040 /* TYPES *********************************************************************/
00041 typedef enum _RPN_OP_TYPE
00042 {
00043     RpnOpNop,
00044     RpnOpBinaryOperator,
00045     RpnOpUnaryOperator,
00046     RpnOpImmediate,
00047     RpnOpRegister,
00048     RpnOpDereference
00049 } RPN_OP_TYPE;
00050 
00051 typedef ULONGLONG (*RPN_BINARY_OPERATOR)(ULONGLONG a, ULONGLONG b);
00052 
00053 typedef struct _RPN_OP
00054 {
00055     RPN_OP_TYPE  Type;
00056     ULONG        CharacterOffset;
00057     union
00058     {
00059         /* RpnOpBinaryOperator */
00060         RPN_BINARY_OPERATOR  BinaryOperator;
00061         /* RpnOpImmediate */
00062         ULONGLONG            Immediate;
00063         /* RpnOpRegister */
00064         UCHAR                Register;
00065         /* RpnOpDereference */
00066         UCHAR                DerefMemorySize;
00067     }
00068     Data;
00069 }
00070 RPN_OP, *PRPN_OP;
00071 
00072 typedef struct _RPN_STACK
00073 {
00074     ULONG   Size;     /* Number of RPN_OPs on Ops */
00075     ULONG   Sp;       /* Stack pointer */
00076     RPN_OP  Ops[1];   /* Array of RPN_OPs */
00077 }
00078 RPN_STACK, *PRPN_STACK;
00079 
00080 /* DEFINES *******************************************************************/
00081 #define stricmp _stricmp
00082 
00083 #ifndef RTL_FIELD_SIZE
00084 # define RTL_FIELD_SIZE(type, field) (sizeof(((type *)0)->field))
00085 #endif
00086 
00087 #define CONST_STRCPY(dst, src) \
00088     do { if ((dst)) { memcpy(dst, src, sizeof(src)); } } while (0);
00089 
00090 #define RPN_OP_STACK_SIZE     256
00091 #define RPN_VALUE_STACK_SIZE  256
00092 
00093 /* GLOBALS *******************************************************************/
00094 static struct
00095 {
00096     ULONG Size;
00097     ULONG Sp;
00098     RPN_OP Ops[RPN_OP_STACK_SIZE];
00099 }
00100 RpnStack =
00101 {
00102     RPN_OP_STACK_SIZE,
00103     0
00104 };
00105 
00106 static const struct
00107 {
00108     PCHAR Name;
00109     UCHAR Offset;
00110     UCHAR Size;
00111 }
00112 RegisterToTrapFrame[] =
00113 {
00114     {"eip",     FIELD_OFFSET(KDB_KTRAP_FRAME, Tf.Eip),     RTL_FIELD_SIZE(KDB_KTRAP_FRAME, Tf.Eip)},
00115     {"eflags",  FIELD_OFFSET(KDB_KTRAP_FRAME, Tf.EFlags),  RTL_FIELD_SIZE(KDB_KTRAP_FRAME, Tf.EFlags)},
00116     {"eax",     FIELD_OFFSET(KDB_KTRAP_FRAME, Tf.Eax),     RTL_FIELD_SIZE(KDB_KTRAP_FRAME, Tf.Eax)},
00117     {"ebx",     FIELD_OFFSET(KDB_KTRAP_FRAME, Tf.Ebx),     RTL_FIELD_SIZE(KDB_KTRAP_FRAME, Tf.Ebx)},
00118     {"ecx",     FIELD_OFFSET(KDB_KTRAP_FRAME, Tf.Ecx),     RTL_FIELD_SIZE(KDB_KTRAP_FRAME, Tf.Ecx)},
00119     {"edx",     FIELD_OFFSET(KDB_KTRAP_FRAME, Tf.Edx),     RTL_FIELD_SIZE(KDB_KTRAP_FRAME, Tf.Edx)},
00120     {"esi",     FIELD_OFFSET(KDB_KTRAP_FRAME, Tf.Esi),     RTL_FIELD_SIZE(KDB_KTRAP_FRAME, Tf.Esi)},
00121     {"edi",     FIELD_OFFSET(KDB_KTRAP_FRAME, Tf.Edi),     RTL_FIELD_SIZE(KDB_KTRAP_FRAME, Tf.Edi)},
00122     {"esp",     FIELD_OFFSET(KDB_KTRAP_FRAME, Tf.HardwareEsp),     RTL_FIELD_SIZE(KDB_KTRAP_FRAME, Tf.HardwareEsp)},
00123     {"ebp",     FIELD_OFFSET(KDB_KTRAP_FRAME, Tf.Ebp),     RTL_FIELD_SIZE(KDB_KTRAP_FRAME, Tf.Ebp)},
00124     {"cs",      FIELD_OFFSET(KDB_KTRAP_FRAME, Tf.SegCs),      2 }, /* Use only the lower 2 bytes */
00125     {"ds",      FIELD_OFFSET(KDB_KTRAP_FRAME, Tf.SegDs),      RTL_FIELD_SIZE(KDB_KTRAP_FRAME, Tf.SegDs)},
00126     {"es",      FIELD_OFFSET(KDB_KTRAP_FRAME, Tf.SegEs),      RTL_FIELD_SIZE(KDB_KTRAP_FRAME, Tf.SegEs)},
00127     {"fs",      FIELD_OFFSET(KDB_KTRAP_FRAME, Tf.SegFs),      RTL_FIELD_SIZE(KDB_KTRAP_FRAME, Tf.SegFs)},
00128     {"gs",      FIELD_OFFSET(KDB_KTRAP_FRAME, Tf.SegGs),      RTL_FIELD_SIZE(KDB_KTRAP_FRAME, Tf.SegGs)},
00129     {"ss",      FIELD_OFFSET(KDB_KTRAP_FRAME, Tf.HardwareSegSs),      RTL_FIELD_SIZE(KDB_KTRAP_FRAME, Tf.HardwareSegSs)},
00130     {"dr0",     FIELD_OFFSET(KDB_KTRAP_FRAME, Tf.Dr0),     RTL_FIELD_SIZE(KDB_KTRAP_FRAME, Tf.Dr0)},
00131     {"dr1",     FIELD_OFFSET(KDB_KTRAP_FRAME, Tf.Dr1),     RTL_FIELD_SIZE(KDB_KTRAP_FRAME, Tf.Dr1)},
00132     {"dr2",     FIELD_OFFSET(KDB_KTRAP_FRAME, Tf.Dr2),     RTL_FIELD_SIZE(KDB_KTRAP_FRAME, Tf.Dr2)},
00133     {"dr3",     FIELD_OFFSET(KDB_KTRAP_FRAME, Tf.Dr3),     RTL_FIELD_SIZE(KDB_KTRAP_FRAME, Tf.Dr3)},
00134     {"dr6",     FIELD_OFFSET(KDB_KTRAP_FRAME, Tf.Dr6),     RTL_FIELD_SIZE(KDB_KTRAP_FRAME, Tf.Dr6)},
00135     {"dr7",     FIELD_OFFSET(KDB_KTRAP_FRAME, Tf.Dr7),     RTL_FIELD_SIZE(KDB_KTRAP_FRAME, Tf.Dr7)},
00136     {"cr0",     FIELD_OFFSET(KDB_KTRAP_FRAME, Cr0),        RTL_FIELD_SIZE(KDB_KTRAP_FRAME, Cr0)},
00137     {"cr2",     FIELD_OFFSET(KDB_KTRAP_FRAME, Cr2),        RTL_FIELD_SIZE(KDB_KTRAP_FRAME, Cr2)},
00138     {"cr3",     FIELD_OFFSET(KDB_KTRAP_FRAME, Cr3),        RTL_FIELD_SIZE(KDB_KTRAP_FRAME, Cr3)},
00139     {"cr4",     FIELD_OFFSET(KDB_KTRAP_FRAME, Cr4),        RTL_FIELD_SIZE(KDB_KTRAP_FRAME, Cr4)}
00140 };
00141 static const INT RegisterToTrapFrameCount = sizeof (RegisterToTrapFrame) / sizeof (RegisterToTrapFrame[0]);
00142 
00143 /* FUNCTIONS *****************************************************************/
00144 
00145 ULONGLONG
00146 RpnBinaryOperatorAdd(
00147     ULONGLONG a,
00148     ULONGLONG b)
00149 {
00150     return a + b;
00151 }
00152 
00153 ULONGLONG
00154 RpnBinaryOperatorSub(
00155     ULONGLONG a,
00156     ULONGLONG b)
00157 {
00158     return a - b;
00159 }
00160 
00161 ULONGLONG
00162 RpnBinaryOperatorMul(
00163     ULONGLONG a,
00164     ULONGLONG b)
00165 {
00166     return a * b;
00167 }
00168 
00169 ULONGLONG
00170 RpnBinaryOperatorDiv(
00171     ULONGLONG a,
00172     ULONGLONG b)
00173 {
00174     return a / b;
00175 }
00176 
00177 ULONGLONG
00178 RpnBinaryOperatorMod(
00179     ULONGLONG a,
00180     ULONGLONG b)
00181 {
00182     return a % b;
00183 }
00184 
00185 ULONGLONG
00186 RpnBinaryOperatorEquals(
00187     ULONGLONG a,
00188     ULONGLONG b)
00189 {
00190     return (a == b);
00191 }
00192 
00193 ULONGLONG
00194 RpnBinaryOperatorNotEquals(
00195     ULONGLONG a,
00196     ULONGLONG b)
00197 {
00198     return (a != b);
00199 }
00200 
00201 ULONGLONG
00202 RpnBinaryOperatorLessThan(
00203     ULONGLONG a,
00204     ULONGLONG b)
00205 {
00206     return (a < b);
00207 }
00208 
00209 ULONGLONG
00210 RpnBinaryOperatorLessThanOrEquals(
00211     ULONGLONG a,
00212     ULONGLONG b)
00213 {
00214     return (a <= b);
00215 }
00216 
00217 ULONGLONG
00218 RpnBinaryOperatorGreaterThan(
00219     ULONGLONG a,
00220     ULONGLONG b)
00221 {
00222     return (a > b);
00223 }
00224 
00225 ULONGLONG
00226 RpnBinaryOperatorGreaterThanOrEquals(
00227     ULONGLONG a,
00228     ULONGLONG b)
00229 {
00230     return (a >= b);
00231 }
00232 
00237 VOID
00238 RpnpDumpStack(
00239     IN PRPN_STACK Stack)
00240 {
00241     ULONG ul;
00242 
00243     ASSERT(Stack);
00244     DbgPrint("\nStack size: %ld\n", Stack->Sp);
00245 
00246     for (ul = 0; ul < Stack->Sp; ul++)
00247     {
00248         PRPN_OP Op = Stack->Ops + ul;
00249         switch (Op->Type)
00250         {
00251             case RpnOpNop:
00252                 DbgPrint("NOP,");
00253                 break;
00254 
00255             case RpnOpImmediate:
00256                 DbgPrint("0x%I64x,", Op->Data.Immediate);
00257                 break;
00258 
00259             case RpnOpBinaryOperator:
00260                 if (Op->Data.BinaryOperator == RpnBinaryOperatorAdd)
00261                     DbgPrint("+,");
00262                 else if (Op->Data.BinaryOperator == RpnBinaryOperatorSub)
00263                     DbgPrint("-,");
00264                 else if (Op->Data.BinaryOperator == RpnBinaryOperatorMul)
00265                     DbgPrint("*,");
00266                 else if (Op->Data.BinaryOperator == RpnBinaryOperatorDiv)
00267                     DbgPrint("/,");
00268                 else if (Op->Data.BinaryOperator == RpnBinaryOperatorMod)
00269                     DbgPrint("%%,");
00270                 else if (Op->Data.BinaryOperator == RpnBinaryOperatorEquals)
00271                     DbgPrint("==,");
00272                 else if (Op->Data.BinaryOperator == RpnBinaryOperatorNotEquals)
00273                     DbgPrint("!=,");
00274                 else if (Op->Data.BinaryOperator == RpnBinaryOperatorLessThan)
00275                     DbgPrint("<,");
00276                 else if (Op->Data.BinaryOperator == RpnBinaryOperatorLessThanOrEquals)
00277                     DbgPrint("<=,");
00278                 else if (Op->Data.BinaryOperator == RpnBinaryOperatorGreaterThan)
00279                     DbgPrint(">,");
00280                 else if (Op->Data.BinaryOperator == RpnBinaryOperatorGreaterThanOrEquals)
00281                     DbgPrint(">=,");
00282                 else
00283                     DbgPrint("UNKNOWN OP,");
00284 
00285                 break;
00286 
00287             case RpnOpRegister:
00288                 DbgPrint("%s,", RegisterToTrapFrame[Op->Data.Register].Name);
00289                 break;
00290 
00291             case RpnOpDereference:
00292                 DbgPrint("[%s],",
00293                     (Op->Data.DerefMemorySize == 1) ? ("byte") :
00294                     ((Op->Data.DerefMemorySize == 2) ? ("word") :
00295                     ((Op->Data.DerefMemorySize == 4) ? ("dword") : ("qword"))));
00296                 break;
00297 
00298             default:
00299                 DbgPrint("\nUnsupported Type: %d\n", Op->Type);
00300                 ul = Stack->Sp;
00301                 break;
00302         }
00303     }
00304 
00305     DbgPrint("\n");
00306 }
00307 
00312 static VOID
00313 RpnpClearStack(
00314     OUT PRPN_STACK Stack)
00315 {
00316     ASSERT(Stack);
00317     Stack->Sp = 0;
00318 }
00319 
00325 static BOOLEAN
00326 RpnpPushStack(
00327     IN OUT PRPN_STACK Stack,
00328     IN     PRPN_OP Op)
00329 {
00330     ASSERT(Stack);
00331     ASSERT(Op);
00332 
00333     if (Stack->Sp >= Stack->Size)
00334         return FALSE;
00335 
00336     memcpy(Stack->Ops + Stack->Sp, Op, sizeof (RPN_OP));
00337     Stack->Sp++;
00338 
00339     return TRUE;
00340 }
00341 
00350 static BOOLEAN
00351 RpnpPopStack(
00352     IN OUT PRPN_STACK Stack,
00353     OUT    PRPN_OP Op  OPTIONAL)
00354 {
00355     ASSERT(Stack);
00356 
00357     if (Stack->Sp == 0)
00358         return FALSE;
00359 
00360     Stack->Sp--;
00361     if (Op)
00362         memcpy(Op, Stack->Ops + Stack->Sp, sizeof (RPN_OP));
00363 
00364     return TRUE;
00365 }
00366 
00375 static BOOLEAN
00376 RpnpTopStack(
00377     IN  PRPN_STACK Stack,
00378     OUT PRPN_OP Op)
00379 {
00380     ASSERT(Stack);
00381     ASSERT(Op);
00382 
00383     if (Stack->Sp == 0)
00384         return FALSE;
00385 
00386     memcpy(Op, Stack->Ops + Stack->Sp - 1, sizeof (RPN_OP));
00387 
00388     return TRUE;
00389 }
00390 
00409 static BOOLEAN
00410 RpnpParseExpression(
00411     IN  PRPN_STACK Stack,
00412     IN  PCHAR Expression,
00413     OUT PCHAR *End  OPTIONAL,
00414     IN  ULONG CharacterOffset,
00415     OUT PLONG ErrOffset  OPTIONAL,
00416     OUT PCHAR ErrMsg  OPTIONAL)
00417 {
00418     PCHAR p = Expression;
00419     PCHAR pend;
00420     PCHAR Operator = NULL;
00421     LONG OperatorOffset = -1;
00422     RPN_OP RpnOp;
00423     RPN_OP PoppedOperator;
00424     BOOLEAN HavePoppedOperator = FALSE;
00425     RPN_OP ComparativeOp;
00426     BOOLEAN ComparativeOpFilled = FALSE;
00427     BOOLEAN IsComparativeOp;
00428     INT i, i2;
00429     ULONG ul;
00430     UCHAR MemorySize;
00431     CHAR Buffer[16];
00432     BOOLEAN First;
00433 
00434     ASSERT(Stack);
00435     ASSERT(Expression);
00436 
00437     First = TRUE;
00438     for (;;)
00439     {
00440         /* Skip whitespace */
00441         while (isspace(*p))
00442         {
00443             p++;
00444             CharacterOffset++;
00445         }
00446 
00447         /* Check for end of expression */
00448         if (p[0] == '\0' || p[0] == ')' || p[0] == ']')
00449             break;
00450 
00451         if (!First)
00452         {
00453             /* Remember operator */
00454             Operator = p++;
00455             OperatorOffset = CharacterOffset++;
00456 
00457             /* Pop operator (to get the right operator precedence) */
00458             HavePoppedOperator = FALSE;
00459             if (*Operator == '*' || *Operator == '/' || *Operator == '%')
00460             {
00461                 if (RpnpTopStack(Stack, &PoppedOperator) &&
00462                     PoppedOperator.Type == RpnOpBinaryOperator &&
00463                     (PoppedOperator.Data.BinaryOperator == RpnBinaryOperatorAdd ||
00464                     PoppedOperator.Data.BinaryOperator == RpnBinaryOperatorSub))
00465                 {
00466                     RpnpPopStack(Stack, NULL);
00467                     HavePoppedOperator = TRUE;
00468                 }
00469                 else if (PoppedOperator.Type == RpnOpNop)
00470                 {
00471                     RpnpPopStack(Stack, NULL);
00472                     /* Discard the NOP - it was only pushed to indicate there was a
00473                      * closing brace, so the previous operator shouldn't be popped.
00474                      */
00475                 }
00476             }
00477             else if ((Operator[0] == '=' && Operator[1] == '=') ||
00478                      (Operator[0] == '!' && Operator[1] == '=') ||
00479                      Operator[0] == '<' || Operator[0] == '>')
00480             {
00481                 if (Operator[0] == '=' || Operator[0] == '!' ||
00482                     (Operator[0] == '<' && Operator[1] == '=') ||
00483                     (Operator[0] == '>' && Operator[1] == '='))
00484                 {
00485                     p++;
00486                     CharacterOffset++;
00487                 }
00488 #if 0
00489                 /* Parse rest of expression */
00490                 if (!RpnpParseExpression(Stack, p + 1, &pend, CharacterOffset + 1,
00491                                          ErrOffset, ErrMsg))
00492                 {
00493                     return FALSE;
00494                 }
00495                 else if (pend == p + 1)
00496                 {
00497                     CONST_STRCPY(ErrMsg, "Expression expected");
00498 
00499                     if (ErrOffset)
00500                         *ErrOffset = CharacterOffset + 1;
00501 
00502                     return FALSE;
00503                 }
00504 
00505                 goto end_of_expression; /* return */
00506 #endif
00507             }
00508             else if (Operator[0] != '+' && Operator[0] != '-')
00509             {
00510                 CONST_STRCPY(ErrMsg, "Operator expected");
00511 
00512                 if (ErrOffset)
00513                     *ErrOffset = OperatorOffset;
00514 
00515                 return FALSE;
00516             }
00517 
00518             /* Skip whitespace */
00519             while (isspace(*p))
00520             {
00521                 p++;
00522                 CharacterOffset++;
00523             }
00524         }
00525 
00526         /* Get operand */
00527         MemorySize = sizeof(ULONG_PTR); /* default to pointer size */
00528 
00529 get_operand:
00530         i = strcspn(p, "+-*/%()[]<>!=");
00531         if (i > 0)
00532         {
00533             i2 = i;
00534 
00535             /* Copy register name/memory size */
00536             while (isspace(p[--i2]));
00537 
00538             i2 = min(i2 + 1, (INT)sizeof (Buffer) - 1);
00539             strncpy(Buffer, p, i2);
00540             Buffer[i2] = '\0';
00541 
00542             /* Memory size prefix */
00543             if (p[i] == '[')
00544             {
00545                 if (stricmp(Buffer, "byte") == 0)
00546                     MemorySize = 1;
00547                 else if (stricmp(Buffer, "word") == 0)
00548                     MemorySize = 2;
00549                 else if (stricmp(Buffer, "dword") == 0)
00550                     MemorySize = 4;
00551                 else if (stricmp(Buffer, "qword") == 0)
00552                     MemorySize = 8;
00553                 else
00554                 {
00555                     CONST_STRCPY(ErrMsg, "Invalid memory size prefix");
00556 
00557                     if (ErrOffset)
00558                         *ErrOffset = CharacterOffset;
00559 
00560                     return FALSE;
00561                 }
00562 
00563                 p += i;
00564                 CharacterOffset += i;
00565                 goto get_operand;
00566             }
00567 
00568             /* Try to find register */
00569             for (i = 0; i < RegisterToTrapFrameCount; i++)
00570             {
00571                 if (stricmp(RegisterToTrapFrame[i].Name, Buffer) == 0)
00572                     break;
00573             }
00574 
00575             if (i < RegisterToTrapFrameCount)
00576             {
00577                 RpnOp.Type = RpnOpRegister;
00578                 RpnOp.CharacterOffset = CharacterOffset;
00579                 RpnOp.Data.Register = i;
00580                 i = strlen(RegisterToTrapFrame[i].Name);
00581                 CharacterOffset += i;
00582                 p += i;
00583             }
00584             else
00585             {
00586                 /* Immediate value */
00587                 /* FIXME: Need string to ULONGLONG function */
00588                 ul = strtoul(p, &pend, 0);
00589                 if (p != pend)
00590                 {
00591                     RpnOp.Type = RpnOpImmediate;
00592                     RpnOp.CharacterOffset = CharacterOffset;
00593                     RpnOp.Data.Immediate = (ULONGLONG)ul;
00594                     CharacterOffset += pend - p;
00595                     p = pend;
00596                 }
00597                 else
00598                 {
00599                     CONST_STRCPY(ErrMsg, "Operand expected");
00600 
00601                     if (ErrOffset)
00602                         *ErrOffset = CharacterOffset;
00603 
00604                     return FALSE;
00605                 }
00606             }
00607 
00608             /* Push operand */
00609             if (!RpnpPushStack(Stack, &RpnOp))
00610             {
00611                 CONST_STRCPY(ErrMsg, "RPN op stack overflow");
00612 
00613                 if (ErrOffset)
00614                     *ErrOffset = -1;
00615 
00616                 return FALSE;
00617             }
00618         }
00619         else if (i == 0)
00620         {
00621             if (p[0] == '(' || p[0] == '[') /* subexpression */
00622             {
00623                 if (!RpnpParseExpression(Stack, p + 1, &pend, CharacterOffset + 1,
00624                                          ErrOffset, ErrMsg))
00625                 {
00626                     return FALSE;
00627                 }
00628                 else if (pend == p + 1)
00629                 {
00630                     CONST_STRCPY(ErrMsg, "Expression expected");
00631 
00632                     if (ErrOffset)
00633                         *ErrOffset = CharacterOffset + 1;
00634 
00635                     return FALSE;
00636                 }
00637 
00638                 if (p[0] == '[') /* dereference */
00639                 {
00640                     ASSERT(MemorySize == 1 || MemorySize == 2 ||
00641                            MemorySize == 4 || MemorySize == 8);
00642 
00643                     if (pend[0] != ']')
00644                     {
00645                         CONST_STRCPY(ErrMsg, "']' expected");
00646 
00647                         if (ErrOffset)
00648                             *ErrOffset = CharacterOffset + (pend - p);
00649 
00650                         return FALSE;
00651                     }
00652 
00653                     RpnOp.Type = RpnOpDereference;
00654                     RpnOp.CharacterOffset = CharacterOffset;
00655                     RpnOp.Data.DerefMemorySize = MemorySize;
00656 
00657                     if (!RpnpPushStack(Stack, &RpnOp))
00658                     {
00659                         CONST_STRCPY(ErrMsg, "RPN op stack overflow");
00660 
00661                         if (ErrOffset)
00662                             *ErrOffset = -1;
00663 
00664                         return FALSE;
00665                     }
00666                 }
00667                 else /* p[0] == '(' */
00668                 {
00669                     if (pend[0] != ')')
00670                     {
00671                         CONST_STRCPY(ErrMsg, "')' expected");
00672 
00673                         if (ErrOffset)
00674                             *ErrOffset = CharacterOffset + (pend - p);
00675 
00676                         return FALSE;
00677                     }
00678                 }
00679 
00680                 /* Push a "nop" to prevent popping of the + operator (which would
00681                  * result in (10+10)/2 beeing evaluated as 15)
00682                  */
00683                 RpnOp.Type = RpnOpNop;
00684                 if (!RpnpPushStack(Stack, &RpnOp))
00685                 {
00686                     CONST_STRCPY(ErrMsg, "RPN op stack overflow");
00687 
00688                     if (ErrOffset)
00689                         *ErrOffset = -1;
00690 
00691                     return FALSE;
00692                 }
00693 
00694                 /* Skip closing brace/bracket */
00695                 pend++;
00696 
00697                 CharacterOffset += pend - p;
00698                 p = pend;
00699             }
00700             else if (First && p[0] == '-') /* Allow expressions like "- eax" */
00701             {
00702                 RpnOp.Type = RpnOpImmediate;
00703                 RpnOp.CharacterOffset = CharacterOffset;
00704                 RpnOp.Data.Immediate = 0;
00705 
00706                 if (!RpnpPushStack(Stack, &RpnOp))
00707                 {
00708                     CONST_STRCPY(ErrMsg, "RPN op stack overflow");
00709 
00710                     if (ErrOffset)
00711                         *ErrOffset = -1;
00712 
00713                     return FALSE;
00714                 }
00715             }
00716             else
00717             {
00718                 CONST_STRCPY(ErrMsg, "Operand expected");
00719 
00720                 if (ErrOffset)
00721                     *ErrOffset = CharacterOffset;
00722 
00723                 return FALSE;
00724             }
00725         }
00726         else
00727         {
00728             CONST_STRCPY(ErrMsg, "strcspn() failed");
00729 
00730             if (ErrOffset)
00731                 *ErrOffset = -1;
00732 
00733             return FALSE;
00734         }
00735 
00736         if (!First)
00737         {
00738             /* Push operator */
00739             RpnOp.CharacterOffset = OperatorOffset;
00740             RpnOp.Type = RpnOpBinaryOperator;
00741             IsComparativeOp = FALSE;
00742 
00743             switch (*Operator)
00744             {
00745                 case '+':
00746                     RpnOp.Data.BinaryOperator = RpnBinaryOperatorAdd;
00747                     break;
00748 
00749                 case '-':
00750                     RpnOp.Data.BinaryOperator = RpnBinaryOperatorSub;
00751                     break;
00752 
00753                 case '*':
00754                     RpnOp.Data.BinaryOperator = RpnBinaryOperatorMul;
00755                     break;
00756 
00757                 case '/':
00758                     RpnOp.Data.BinaryOperator = RpnBinaryOperatorDiv;
00759                     break;
00760 
00761                 case '%':
00762                     RpnOp.Data.BinaryOperator = RpnBinaryOperatorMod;
00763                     break;
00764 
00765                 case '=':
00766                     ASSERT(Operator[1] == '=');
00767                     IsComparativeOp = TRUE;
00768                     RpnOp.Data.BinaryOperator = RpnBinaryOperatorEquals;
00769                     break;
00770 
00771                 case '!':
00772                     ASSERT(Operator[1] == '=');
00773                     IsComparativeOp = TRUE;
00774                     RpnOp.Data.BinaryOperator = RpnBinaryOperatorNotEquals;
00775                     break;
00776 
00777                 case '<':
00778                     IsComparativeOp = TRUE;
00779 
00780                     if (Operator[1] == '=')
00781                         RpnOp.Data.BinaryOperator = RpnBinaryOperatorLessThanOrEquals;
00782                     else
00783                         RpnOp.Data.BinaryOperator = RpnBinaryOperatorLessThan;
00784 
00785                     break;
00786 
00787                 case '>':
00788                     IsComparativeOp = TRUE;
00789 
00790                     if (Operator[1] == '=')
00791                         RpnOp.Data.BinaryOperator = RpnBinaryOperatorGreaterThanOrEquals;
00792                     else
00793                         RpnOp.Data.BinaryOperator = RpnBinaryOperatorGreaterThan;
00794 
00795                     break;
00796 
00797                 default:
00798                     ASSERT(0);
00799                     break;
00800             }
00801 
00802             if (IsComparativeOp)
00803             {
00804                 if (ComparativeOpFilled && !RpnpPushStack(Stack, &ComparativeOp))
00805                 {
00806                     CONST_STRCPY(ErrMsg, "RPN op stack overflow");
00807 
00808                     if (ErrOffset)
00809                         *ErrOffset = -1;
00810 
00811                     return FALSE;
00812                 }
00813 
00814                 memcpy(&ComparativeOp, &RpnOp, sizeof(RPN_OP));
00815                 ComparativeOpFilled = TRUE;
00816             }
00817             else if (!RpnpPushStack(Stack, &RpnOp))
00818             {
00819                 CONST_STRCPY(ErrMsg, "RPN op stack overflow");
00820 
00821                 if (ErrOffset)
00822                     *ErrOffset = -1;
00823 
00824                 return FALSE;
00825             }
00826 
00827             /* Push popped operator */
00828             if (HavePoppedOperator)
00829             {
00830                 if (!RpnpPushStack(Stack, &PoppedOperator))
00831                 {
00832                     CONST_STRCPY(ErrMsg, "RPN op stack overflow");
00833 
00834                     if (ErrOffset)
00835                         *ErrOffset = -1;
00836 
00837                     return FALSE;
00838                 }
00839             }
00840         }
00841 
00842         First = FALSE;
00843     }
00844 
00845 //end_of_expression:
00846 
00847     if (ComparativeOpFilled && !RpnpPushStack(Stack, &ComparativeOp))
00848     {
00849         CONST_STRCPY(ErrMsg, "RPN op stack overflow");
00850 
00851         if (ErrOffset)
00852             *ErrOffset = -1;
00853 
00854         return FALSE;
00855     }
00856 
00857     /* Skip whitespace */
00858     while (isspace(*p))
00859     {
00860         p++;
00861         CharacterOffset++;
00862     }
00863 
00864     if (End)
00865         *End = p;
00866 
00867     return TRUE;
00868 }
00869 
00881 static BOOLEAN
00882 RpnpEvaluateStack(
00883     IN  PRPN_STACK Stack,
00884     IN  PKDB_KTRAP_FRAME TrapFrame,
00885     OUT PULONGLONG Result,
00886     OUT PLONG ErrOffset  OPTIONAL,
00887     OUT PCHAR ErrMsg  OPTIONAL)
00888 {
00889     ULONGLONG ValueStack[RPN_VALUE_STACK_SIZE];
00890     ULONG ValueStackPointer = 0;
00891     ULONG index;
00892     ULONGLONG ull;
00893     ULONG ul;
00894     USHORT us;
00895     UCHAR uc;
00896     PVOID p;
00897     BOOLEAN Ok;
00898 #ifdef DEBUG_RPN
00899     ULONG ValueStackPointerMax = 0;
00900 #endif
00901 
00902     ASSERT(Stack);
00903     ASSERT(TrapFrame);
00904     ASSERT(Result);
00905 
00906     for (index = 0; index < Stack->Sp; index++)
00907     {
00908         PRPN_OP Op = Stack->Ops + index;
00909 
00910 #ifdef DEBUG_RPN
00911         ValueStackPointerMax = max(ValueStackPointerMax, ValueStackPointer);
00912 #endif
00913 
00914         switch (Op->Type)
00915         {
00916             case RpnOpNop:
00917                 /* No operation */
00918                 break;
00919 
00920             case RpnOpImmediate:
00921                 if (ValueStackPointer == RPN_VALUE_STACK_SIZE)
00922                 {
00923                     CONST_STRCPY(ErrMsg, "Value stack overflow");
00924 
00925                     if (ErrOffset)
00926                         *ErrOffset = -1;
00927 
00928                     return FALSE;
00929                 }
00930 
00931                 ValueStack[ValueStackPointer++] = Op->Data.Immediate;
00932                 break;
00933 
00934             case RpnOpRegister:
00935                 if (ValueStackPointer == RPN_VALUE_STACK_SIZE)
00936                 {
00937                     CONST_STRCPY(ErrMsg, "Value stack overflow");
00938 
00939                     if (ErrOffset)
00940                         *ErrOffset = -1;
00941 
00942                     return FALSE;
00943                 }
00944 
00945                 ul = Op->Data.Register;
00946                 p = (PVOID)((ULONG_PTR)TrapFrame + RegisterToTrapFrame[ul].Offset);
00947 
00948                 switch (RegisterToTrapFrame[ul].Size)
00949                 {
00950                     case 1: ull = (ULONGLONG)(*(PUCHAR)p); break;
00951                     case 2: ull = (ULONGLONG)(*(PUSHORT)p); break;
00952                     case 4: ull = (ULONGLONG)(*(PULONG)p); break;
00953                     case 8: ull = (ULONGLONG)(*(PULONGLONG)p); break;
00954                     default: ASSERT(0); return FALSE; break;
00955                 }
00956 
00957                 ValueStack[ValueStackPointer++] = ull;
00958                 break;
00959 
00960             case RpnOpDereference:
00961                 if (ValueStackPointer < 1)
00962                 {
00963                     CONST_STRCPY(ErrMsg, "Value stack underflow");
00964 
00965                     if (ErrOffset)
00966                         *ErrOffset = -1;
00967 
00968                     return FALSE;
00969                 }
00970 
00971                 /* FIXME: Print a warning when address is out of range */
00972                 p = (PVOID)(ULONG_PTR)ValueStack[ValueStackPointer - 1];
00973                 Ok = FALSE;
00974 
00975                 switch (Op->Data.DerefMemorySize)
00976                 {
00977                     case 1:
00978                         if (NT_SUCCESS(KdbpSafeReadMemory(&uc, p, sizeof (uc))))
00979                         {
00980                             Ok = TRUE;
00981                             ull = (ULONGLONG)uc;
00982                         }
00983                         break;
00984 
00985                     case 2:
00986                         if (NT_SUCCESS(KdbpSafeReadMemory(&us, p, sizeof (us))))
00987                         {
00988                             Ok = TRUE;
00989                             ull = (ULONGLONG)us;
00990                         }
00991                         break;
00992 
00993                     case 4:
00994                         if (NT_SUCCESS(KdbpSafeReadMemory(&ul, p, sizeof (ul))))
00995                         {
00996                             Ok = TRUE;
00997                             ull = (ULONGLONG)ul;
00998                         }
00999                         break;
01000 
01001                     case 8:
01002                         if (NT_SUCCESS(KdbpSafeReadMemory(&ull, p, sizeof (ull))))
01003                         {
01004                             Ok = TRUE;
01005                         }
01006                         break;
01007 
01008                     default:
01009                         ASSERT(0);
01010                         return FALSE;
01011                         break;
01012                 }
01013 
01014                 if (!Ok)
01015                 {
01016                     _snprintf(ErrMsg, 128, "Couldn't access memory at 0x%lx", (ULONG)p);
01017 
01018                     if (ErrOffset)
01019                         *ErrOffset = Op->CharacterOffset;
01020 
01021                     return FALSE;
01022                 }
01023 
01024                 ValueStack[ValueStackPointer - 1] = ull;
01025                 break;
01026 
01027             case RpnOpBinaryOperator:
01028                 if (ValueStackPointer < 2)
01029                 {
01030                     CONST_STRCPY(ErrMsg, "Value stack underflow");
01031 
01032                     if (ErrOffset)
01033                         *ErrOffset = -1;
01034 
01035                     return FALSE;
01036                 }
01037 
01038                 ValueStackPointer--;
01039                 ull = ValueStack[ValueStackPointer];
01040 
01041                 if (ull == 0 && Op->Data.BinaryOperator == RpnBinaryOperatorDiv)
01042                 {
01043                     CONST_STRCPY(ErrMsg, "Division by zero");
01044 
01045                     if (ErrOffset)
01046                         *ErrOffset = Op->CharacterOffset;
01047 
01048                     return FALSE;
01049                 }
01050 
01051                 ull = Op->Data.BinaryOperator(ValueStack[ValueStackPointer - 1], ull);
01052                 ValueStack[ValueStackPointer - 1] = ull;
01053                 break;
01054 
01055             default:
01056                 ASSERT(0);
01057                 return FALSE;
01058         }
01059     }
01060 
01061 #ifdef DEBUG_RPN
01062     DPRINT1("Max value stack pointer: %d\n", ValueStackPointerMax);
01063 #endif
01064 
01065     if (ValueStackPointer != 1)
01066     {
01067         CONST_STRCPY(ErrMsg, "Stack not empty after evaluation");
01068 
01069         if (ErrOffset)
01070             *ErrOffset = -1;
01071 
01072         return FALSE;
01073     }
01074 
01075     *Result = ValueStack[0];
01076     return TRUE;
01077 }
01078 
01090 BOOLEAN
01091 KdbpRpnEvaluateExpression(
01092     IN  PCHAR Expression,
01093     IN  PKDB_KTRAP_FRAME TrapFrame,
01094     OUT PULONGLONG Result,
01095     OUT PLONG ErrOffset  OPTIONAL,
01096     OUT PCHAR ErrMsg  OPTIONAL)
01097 {
01098     PRPN_STACK Stack = (PRPN_STACK)&RpnStack;
01099 
01100     ASSERT(Expression);
01101     ASSERT(TrapFrame);
01102     ASSERT(Result);
01103 
01104     /* Clear the stack and parse the expression */
01105     RpnpClearStack(Stack);
01106     if (!RpnpParseExpression(Stack, Expression, NULL, 0, ErrOffset, ErrMsg))
01107         return FALSE;
01108 
01109 #ifdef DEBUG_RPN
01110     RpnpDumpStack(Stack);
01111 #endif
01112 
01113     /* Evaluate the stack */
01114     if (!RpnpEvaluateStack(Stack, TrapFrame, Result, ErrOffset, ErrMsg))
01115         return FALSE;
01116 
01117     return TRUE;
01118 }
01119 
01130 PVOID
01131 KdbpRpnParseExpression(
01132     IN  PCHAR Expression,
01133     OUT PLONG ErrOffset  OPTIONAL,
01134     OUT PCHAR ErrMsg  OPTIONAL)
01135 {
01136     LONG Size;
01137     PRPN_STACK Stack = (PRPN_STACK)&RpnStack;
01138     PRPN_STACK NewStack;
01139 
01140     ASSERT(Expression);
01141 
01142     /* Clear the stack and parse the expression */
01143     RpnpClearStack(Stack);
01144     if (!RpnpParseExpression(Stack, Expression, NULL, 0, ErrOffset, ErrMsg))
01145         return FALSE;
01146 
01147 #ifdef DEBUG_RPN
01148     RpnpDumpStack(Stack);
01149 #endif
01150 
01151     /* Duplicate the stack and return a pointer/handle to it */
01152     ASSERT(Stack->Sp >= 1);
01153     Size = sizeof (RPN_STACK) + (RTL_FIELD_SIZE(RPN_STACK, Ops[0]) * (Stack->Sp - 1));
01154     NewStack = ExAllocatePoolWithTag(NonPagedPool, Size, TAG_KDBG);
01155 
01156     if (!NewStack)
01157     {
01158         CONST_STRCPY(ErrMsg, "Out of memory");
01159 
01160         if (ErrOffset)
01161             *ErrOffset = -1;
01162 
01163         return NULL;
01164     }
01165 
01166     memcpy(NewStack, Stack, Size);
01167     NewStack->Size = NewStack->Sp;
01168 
01169     return NewStack;
01170 }
01171 
01184 BOOLEAN
01185 KdbpRpnEvaluateParsedExpression(
01186     IN  PVOID Expression,
01187     IN  PKDB_KTRAP_FRAME TrapFrame,
01188     OUT PULONGLONG Result,
01189     OUT PLONG ErrOffset  OPTIONAL,
01190     OUT PCHAR ErrMsg  OPTIONAL)
01191 {
01192     PRPN_STACK Stack = (PRPN_STACK)Expression;
01193 
01194     ASSERT(Expression);
01195     ASSERT(TrapFrame);
01196     ASSERT(Result);
01197 
01198     /* Evaluate the stack */
01199     return RpnpEvaluateStack(Stack, TrapFrame, Result, ErrOffset, ErrMsg);
01200 }
01201 

Generated on Sun May 27 2012 04:37:29 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.