VirtualBox

source: vbox/trunk/src/VBox/Debugger/DBGCOps.cpp@ 35439

Last change on this file since 35439 was 35439, checked in by vboxsync, 14 years ago

DBGCOps.cpp: Added register op (@) stub.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 58.6 KB
Line 
1/* $Id: DBGCOps.cpp 35439 2011-01-09 23:39:53Z vboxsync $ */
2/** @file
3 * DBGC - Debugger Console, Operators.
4 */
5
6/*
7 * Copyright (C) 2006-2010 Oracle Corporation
8 *
9 * This file is part of VirtualBox Open Source Edition (OSE), as
10 * available from http://www.virtualbox.org. This file is free software;
11 * you can redistribute it and/or modify it under the terms of the GNU
12 * General Public License (GPL) as published by the Free Software
13 * Foundation, in version 2 as it comes in the "COPYING" file of the
14 * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
15 * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
16 */
17
18
19/*******************************************************************************
20* Header Files *
21*******************************************************************************/
22#define LOG_GROUP LOG_GROUP_DBGC
23#include <VBox/dbg.h>
24#include <VBox/vmm/dbgf.h>
25#include <VBox/vmm/vm.h>
26#include <VBox/vmm/vmm.h>
27#include <VBox/vmm/mm.h>
28#include <VBox/vmm/pgm.h>
29#include <VBox/vmm/selm.h>
30#include <VBox/dis.h>
31#include <VBox/param.h>
32#include <VBox/err.h>
33#include <VBox/log.h>
34
35#include <iprt/alloc.h>
36#include <iprt/alloca.h>
37#include <iprt/string.h>
38#include <iprt/assert.h>
39#include <iprt/ctype.h>
40
41#include <stdlib.h>
42#include <stdio.h>
43
44#include "DBGCInternal.h"
45
46
47/*******************************************************************************
48* Internal Functions *
49*******************************************************************************/
50static DECLCALLBACK(int) dbgcOpMinus(PDBGC pDbgc, PCDBGCVAR pArg, PDBGCVAR pResult);
51static DECLCALLBACK(int) dbgcOpPluss(PDBGC pDbgc, PCDBGCVAR pArg, PDBGCVAR pResult);
52static DECLCALLBACK(int) dbgcOpBooleanNot(PDBGC pDbgc, PCDBGCVAR pArg, PDBGCVAR pResult);
53static DECLCALLBACK(int) dbgcOpBitwiseNot(PDBGC pDbgc, PCDBGCVAR pArg, PDBGCVAR pResult);
54static DECLCALLBACK(int) dbgcOpVar(PDBGC pDbgc, PCDBGCVAR pArg, PDBGCVAR pResult);
55static DECLCALLBACK(int) dbgcOpRegister(PDBGC pDbgc, PCDBGCVAR pArg, PDBGCVAR pResult);
56
57static DECLCALLBACK(int) dbgcOpAddrFar(PDBGC pDbgc, PCDBGCVAR pArg1, PCDBGCVAR pArg2, PDBGCVAR pResult);
58static DECLCALLBACK(int) dbgcOpMult(PDBGC pDbgc, PCDBGCVAR pArg1, PCDBGCVAR pArg2, PDBGCVAR pResult);
59static DECLCALLBACK(int) dbgcOpDiv(PDBGC pDbgc, PCDBGCVAR pArg1, PCDBGCVAR pArg2, PDBGCVAR pResult);
60static DECLCALLBACK(int) dbgcOpMod(PDBGC pDbgc, PCDBGCVAR pArg1, PCDBGCVAR pArg2, PDBGCVAR pResult);
61static DECLCALLBACK(int) dbgcOpAdd(PDBGC pDbgc, PCDBGCVAR pArg1, PCDBGCVAR pArg2, PDBGCVAR pResult);
62static DECLCALLBACK(int) dbgcOpSub(PDBGC pDbgc, PCDBGCVAR pArg1, PCDBGCVAR pArg2, PDBGCVAR pResult);
63static DECLCALLBACK(int) dbgcOpBitwiseShiftLeft(PDBGC pDbgc, PCDBGCVAR pArg1, PCDBGCVAR pArg2, PDBGCVAR pResult);
64static DECLCALLBACK(int) dbgcOpBitwiseShiftRight(PDBGC pDbgc, PCDBGCVAR pArg1, PCDBGCVAR pArg2, PDBGCVAR pResult);
65static DECLCALLBACK(int) dbgcOpBitwiseAnd(PDBGC pDbgc, PCDBGCVAR pArg1, PCDBGCVAR pArg2, PDBGCVAR pResult);
66static DECLCALLBACK(int) dbgcOpBitwiseXor(PDBGC pDbgc, PCDBGCVAR pArg1, PCDBGCVAR pArg2, PDBGCVAR pResult);
67static DECLCALLBACK(int) dbgcOpBitwiseOr(PDBGC pDbgc, PCDBGCVAR pArg1, PCDBGCVAR pArg2, PDBGCVAR pResult);
68static DECLCALLBACK(int) dbgcOpBooleanAnd(PDBGC pDbgc, PCDBGCVAR pArg1, PCDBGCVAR pArg2, PDBGCVAR pResult);
69static DECLCALLBACK(int) dbgcOpBooleanOr(PDBGC pDbgc, PCDBGCVAR pArg1, PCDBGCVAR pArg2, PDBGCVAR pResult);
70static DECLCALLBACK(int) dbgcOpRangeLength(PDBGC pDbgc, PCDBGCVAR pArg1, PCDBGCVAR pArg2, PDBGCVAR pResult);
71static DECLCALLBACK(int) dbgcOpRangeLengthBytes(PDBGC pDbgc, PCDBGCVAR pArg1, PCDBGCVAR pArg2, PDBGCVAR pResult);
72static DECLCALLBACK(int) dbgcOpRangeTo(PDBGC pDbgc, PCDBGCVAR pArg1, PCDBGCVAR pArg2, PDBGCVAR pResult);
73
74
75/*******************************************************************************
76* Defined Constants And Macros *
77*******************************************************************************/
78/**
79 * Generic implementation of a binary operator.
80 *
81 * @returns VINF_SUCCESS on success.
82 * @returns VBox evaluation / parsing error code on failure.
83 * The caller does the bitching.
84 * @param pDbgc Debugger console instance data.
85 * @param pArg1 The first argument.
86 * @param pArg2 The 2nd argument.
87 * @param pResult Where to store the result.
88 * @param Operator The C operator.
89 * @param fIsDiv Set if it's division and we need to check for zero on the
90 * right hand side.
91 */
92#define DBGC_GEN_ARIT_BINARY_OP(pDbgc, pArg1, pArg2, pResult, Operator, fIsDiv) \
93 do \
94 { \
95 /* Get the 64-bit right side value. */ \
96 uint64_t u64Right; \
97 int rc = dbgcOpHelperGetNumber((pDbgc), (pArg2), &u64Right); \
98 if ((fIsDiv) && RT_SUCCESS(rc) && !u64Right) /* div/0 kludge */ \
99 DBGCVAR_INIT_NUMBER((pResult), UINT64_MAX); \
100 else if (RT_SUCCESS(rc)) \
101 { \
102 /* Apply it to the left hand side. */ \
103 if ( (pArg1)->enmType == DBGCVAR_TYPE_SYMBOL \
104 || (pArg1)->enmType == DBGCVAR_TYPE_STRING) \
105 { \
106 rc = dbgcSymbolGet((pDbgc), (pArg1)->u.pszString, DBGCVAR_TYPE_ANY, (pResult)); \
107 if (RT_FAILURE(rc)) \
108 return rc; \
109 } \
110 else \
111 *(pResult) = *(pArg1); \
112 switch ((pResult)->enmType) \
113 { \
114 case DBGCVAR_TYPE_GC_FLAT: \
115 (pResult)->u.GCFlat = (pResult)->u.GCFlat Operator u64Right; \
116 break; \
117 case DBGCVAR_TYPE_GC_FAR: \
118 (pResult)->u.GCFar.off = (pResult)->u.GCFar.off Operator u64Right; \
119 break; \
120 case DBGCVAR_TYPE_GC_PHYS: \
121 (pResult)->u.GCPhys = (pResult)->u.GCPhys Operator u64Right; \
122 break; \
123 case DBGCVAR_TYPE_HC_FLAT: \
124 (pResult)->u.pvHCFlat = (void *)((uintptr_t)(pResult)->u.pvHCFlat Operator u64Right); \
125 break; \
126 case DBGCVAR_TYPE_HC_FAR: \
127 (pResult)->u.HCFar.off = (pResult)->u.HCFar.off Operator u64Right; \
128 break; \
129 case DBGCVAR_TYPE_HC_PHYS: \
130 (pResult)->u.HCPhys = (pResult)->u.HCPhys Operator u64Right; \
131 break; \
132 case DBGCVAR_TYPE_NUMBER: \
133 (pResult)->u.u64Number = (pResult)->u.u64Number Operator u64Right; \
134 break; \
135 default: \
136 return VERR_PARSE_INCORRECT_ARG_TYPE; \
137 } \
138 } \
139 return rc; \
140 } while (0)
141
142
143/**
144 * Switch the factors/whatever so we preserve pointers.
145 * Far pointers are considered more important that physical and flat pointers.
146 *
147 * @param pArg1 The left side argument. Input & output.
148 * @param pArg2 The right side argument. Input & output.
149 */
150#define DBGC_GEN_ARIT_POINTER_TO_THE_LEFT(pArg1, pArg2) \
151 do \
152 { \
153 if ( DBGCVAR_ISPOINTER((pArg2)->enmType) \
154 && ( !DBGCVAR_ISPOINTER((pArg1)->enmType) \
155 || ( DBGCVAR_IS_FAR_PTR((pArg2)->enmType) \
156 && !DBGCVAR_IS_FAR_PTR((pArg1)->enmType)))) \
157 { \
158 PCDBGCVAR pTmp = (pArg1); \
159 (pArg2) = (pArg1); \
160 (pArg1) = pTmp; \
161 } \
162 } while (0)
163
164
165/*******************************************************************************
166* Global Variables *
167*******************************************************************************/
168/** Operators. */
169const DBGCOP g_aOps[] =
170{
171 /* szName is initialized as a 4 char array because of M$C elsewise optimizing it away in /Ox mode (the 'const char' vs 'char' problem). */
172 /* szName, cchName, fBinary, iPrecedence, pfnHandlerUnary, pfnHandlerBitwise */
173 { {'-'}, 1, false, 1, dbgcOpMinus, NULL, "Unary minus." },
174 { {'+'}, 1, false, 1, dbgcOpPluss, NULL, "Unary plus." },
175 { {'!'}, 1, false, 1, dbgcOpBooleanNot, NULL, "Boolean not." },
176 { {'~'}, 1, false, 1, dbgcOpBitwiseNot, NULL, "Bitwise complement." },
177 { {':'}, 1, true, 2, NULL, dbgcOpAddrFar, "Far pointer." },
178 { {'%'}, 1, false, 3, dbgcOpAddrFlat, NULL, "Flat address." },
179 { {'%','%'}, 2, false, 3, dbgcOpAddrPhys, NULL, "Physical address." },
180 { {'#'}, 1, false, 3, dbgcOpAddrHost, NULL, "Flat host address." },
181 { {'#','%','%'}, 3, false, 3, dbgcOpAddrHostPhys, NULL, "Physical host address." },
182 { {'$'}, 1, false, 3, dbgcOpVar, NULL, "Reference a variable." },
183 { {'@'}, 1, false, 3, dbgcOpRegister, NULL, "Reference a register." },
184 { {'*'}, 1, true, 10, NULL, dbgcOpMult, "Multiplication." },
185 { {'/'}, 1, true, 11, NULL, dbgcOpDiv, "Division." },
186 { {'%'}, 1, true, 12, NULL, dbgcOpMod, "Modulus." },
187 { {'+'}, 1, true, 13, NULL, dbgcOpAdd, "Addition." },
188 { {'-'}, 1, true, 14, NULL, dbgcOpSub, "Subtraction." },
189 { {'<','<'}, 2, true, 15, NULL, dbgcOpBitwiseShiftLeft, "Bitwise left shift." },
190 { {'>','>'}, 2, true, 16, NULL, dbgcOpBitwiseShiftRight, "Bitwise right shift." },
191 { {'&'}, 1, true, 17, NULL, dbgcOpBitwiseAnd, "Bitwise and." },
192 { {'^'}, 1, true, 18, NULL, dbgcOpBitwiseXor, "Bitwise exclusiv or." },
193 { {'|'}, 1, true, 19, NULL, dbgcOpBitwiseOr, "Bitwise inclusive or." },
194 { {'&','&'}, 2, true, 20, NULL, dbgcOpBooleanAnd, "Boolean and." },
195 { {'|','|'}, 2, true, 21, NULL, dbgcOpBooleanOr, "Boolean or." },
196 { {'L'}, 1, true, 22, NULL, dbgcOpRangeLength, "Range elements." },
197 { {'L','B'}, 2, true, 23, NULL, dbgcOpRangeLengthBytes, "Range bytes." },
198 { {'T'}, 1, true, 24, NULL, dbgcOpRangeTo, "Range to." }
199};
200
201/** Number of operators in the operator array. */
202const unsigned g_cOps = RT_ELEMENTS(g_aOps);
203
204
205/**
206 * Converts an argument to a number value.
207 *
208 * @returns VBox status code.
209 * @param pDbgc The DBGC instance.
210 * @param pArg The argument to convert.
211 * @param pu64Ret Where to return the value.
212 */
213static int dbgcOpHelperGetNumber(PDBGC pDbgc, PCDBGCVAR pArg, uint64_t *pu64Ret)
214{
215 DBGCVAR Var = *pArg;
216 switch (Var.enmType)
217 {
218 case DBGCVAR_TYPE_GC_FLAT:
219 *pu64Ret = Var.u.GCFlat;
220 break;
221 case DBGCVAR_TYPE_GC_FAR:
222 *pu64Ret = Var.u.GCFar.off;
223 break;
224 case DBGCVAR_TYPE_GC_PHYS:
225 *pu64Ret = Var.u.GCPhys;
226 break;
227 case DBGCVAR_TYPE_HC_FLAT:
228 *pu64Ret = (uintptr_t)Var.u.pvHCFlat;
229 break;
230 case DBGCVAR_TYPE_HC_FAR:
231 *pu64Ret = Var.u.HCFar.off;
232 break;
233 case DBGCVAR_TYPE_HC_PHYS:
234 *pu64Ret = Var.u.HCPhys;
235 break;
236 case DBGCVAR_TYPE_STRING:
237 case DBGCVAR_TYPE_SYMBOL:
238 {
239 int rc = dbgcSymbolGet(pDbgc, Var.u.pszString, DBGCVAR_TYPE_NUMBER, &Var);
240 if (RT_FAILURE(rc))
241 return rc;
242 /* fall thru */
243 }
244 case DBGCVAR_TYPE_NUMBER:
245 *pu64Ret = Var.u.u64Number;
246 break;
247 default:
248 return VERR_PARSE_INCORRECT_ARG_TYPE;
249 }
250 return VINF_SUCCESS;
251}
252
253
254/**
255 * Minus (unary).
256 *
257 * @returns VINF_SUCCESS on success.
258 * @returns VBox evaluation / parsing error code on failure.
259 * The caller does the bitching.
260 * @param pDbgc Debugger console instance data.
261 * @param pArg The argument.
262 * @param pResult Where to store the result.
263 */
264static DECLCALLBACK(int) dbgcOpMinus(PDBGC pDbgc, PCDBGCVAR pArg, PDBGCVAR pResult)
265{
266 LogFlow(("dbgcOpMinus\n"));
267 *pResult = *pArg;
268 switch (pArg->enmType)
269 {
270 case DBGCVAR_TYPE_GC_FLAT:
271 pResult->u.GCFlat = -(RTGCINTPTR)pResult->u.GCFlat;
272 break;
273 case DBGCVAR_TYPE_GC_FAR:
274 pResult->u.GCFar.off = -(int32_t)pResult->u.GCFar.off;
275 break;
276 case DBGCVAR_TYPE_GC_PHYS:
277 pResult->u.GCPhys = (RTGCPHYS) -(int64_t)pResult->u.GCPhys;
278 break;
279 case DBGCVAR_TYPE_HC_FLAT:
280 pResult->u.pvHCFlat = (void *) -(intptr_t)pResult->u.pvHCFlat;
281 break;
282 case DBGCVAR_TYPE_HC_FAR:
283 pResult->u.HCFar.off = -(int32_t)pResult->u.HCFar.off;
284 break;
285 case DBGCVAR_TYPE_HC_PHYS:
286 pResult->u.HCPhys = (RTHCPHYS) -(int64_t)pResult->u.HCPhys;
287 break;
288 case DBGCVAR_TYPE_NUMBER:
289 pResult->u.u64Number = -(int64_t)pResult->u.u64Number;
290 break;
291
292 case DBGCVAR_TYPE_UNKNOWN:
293 case DBGCVAR_TYPE_STRING:
294 default:
295 return VERR_PARSE_INCORRECT_ARG_TYPE;
296 }
297 NOREF(pDbgc);
298 return VINF_SUCCESS;
299}
300
301
302/**
303 * Plus (unary).
304 *
305 * @returns VINF_SUCCESS on success.
306 * @returns VBox evaluation / parsing error code on failure.
307 * The caller does the bitching.
308 * @param pDbgc Debugger console instance data.
309 * @param pArg The argument.
310 * @param pResult Where to store the result.
311 */
312static DECLCALLBACK(int) dbgcOpPluss(PDBGC pDbgc, PCDBGCVAR pArg, PDBGCVAR pResult)
313{
314 LogFlow(("dbgcOpPluss\n"));
315 *pResult = *pArg;
316 switch (pArg->enmType)
317 {
318 case DBGCVAR_TYPE_GC_FLAT:
319 case DBGCVAR_TYPE_GC_FAR:
320 case DBGCVAR_TYPE_GC_PHYS:
321 case DBGCVAR_TYPE_HC_FLAT:
322 case DBGCVAR_TYPE_HC_FAR:
323 case DBGCVAR_TYPE_HC_PHYS:
324 case DBGCVAR_TYPE_NUMBER:
325 break;
326
327 case DBGCVAR_TYPE_UNKNOWN:
328 case DBGCVAR_TYPE_STRING:
329 default:
330 return VERR_PARSE_INCORRECT_ARG_TYPE;
331 }
332 NOREF(pDbgc);
333 return VINF_SUCCESS;
334}
335
336
337/**
338 * Boolean not (unary).
339 *
340 * @returns VINF_SUCCESS on success.
341 * @returns VBox evaluation / parsing error code on failure.
342 * The caller does the bitching.
343 * @param pDbgc Debugger console instance data.
344 * @param pArg The argument.
345 * @param pResult Where to store the result.
346 */
347static DECLCALLBACK(int) dbgcOpBooleanNot(PDBGC pDbgc, PCDBGCVAR pArg, PDBGCVAR pResult)
348{
349 LogFlow(("dbgcOpBooleanNot\n"));
350 *pResult = *pArg;
351 switch (pArg->enmType)
352 {
353 case DBGCVAR_TYPE_GC_FLAT:
354 pResult->u.u64Number = !pResult->u.GCFlat;
355 break;
356 case DBGCVAR_TYPE_GC_FAR:
357 pResult->u.u64Number = !pResult->u.GCFar.off && pResult->u.GCFar.sel <= 3;
358 break;
359 case DBGCVAR_TYPE_GC_PHYS:
360 pResult->u.u64Number = !pResult->u.GCPhys;
361 break;
362 case DBGCVAR_TYPE_HC_FLAT:
363 pResult->u.u64Number = !pResult->u.pvHCFlat;
364 break;
365 case DBGCVAR_TYPE_HC_FAR:
366 pResult->u.u64Number = !pResult->u.HCFar.off && pResult->u.HCFar.sel <= 3;
367 break;
368 case DBGCVAR_TYPE_HC_PHYS:
369 pResult->u.u64Number = !pResult->u.HCPhys;
370 break;
371 case DBGCVAR_TYPE_NUMBER:
372 pResult->u.u64Number = !pResult->u.u64Number;
373 break;
374 case DBGCVAR_TYPE_STRING:
375 pResult->u.u64Number = !pResult->u64Range;
376 break;
377
378 case DBGCVAR_TYPE_UNKNOWN:
379 default:
380 return VERR_PARSE_INCORRECT_ARG_TYPE;
381 }
382 pResult->enmType = DBGCVAR_TYPE_NUMBER;
383 NOREF(pDbgc);
384 return VINF_SUCCESS;
385}
386
387
388/**
389 * Bitwise not (unary).
390 *
391 * @returns VINF_SUCCESS on success.
392 * @returns VBox evaluation / parsing error code on failure.
393 * The caller does the bitching.
394 * @param pDbgc Debugger console instance data.
395 * @param pArg The argument.
396 * @param pResult Where to store the result.
397 */
398static DECLCALLBACK(int) dbgcOpBitwiseNot(PDBGC pDbgc, PCDBGCVAR pArg, PDBGCVAR pResult)
399{
400 LogFlow(("dbgcOpBitwiseNot\n"));
401 *pResult = *pArg;
402 switch (pArg->enmType)
403 {
404 case DBGCVAR_TYPE_GC_FLAT:
405 pResult->u.GCFlat = ~pResult->u.GCFlat;
406 break;
407 case DBGCVAR_TYPE_GC_FAR:
408 pResult->u.GCFar.off = ~pResult->u.GCFar.off;
409 break;
410 case DBGCVAR_TYPE_GC_PHYS:
411 pResult->u.GCPhys = ~pResult->u.GCPhys;
412 break;
413 case DBGCVAR_TYPE_HC_FLAT:
414 pResult->u.pvHCFlat = (void *)~(uintptr_t)pResult->u.pvHCFlat;
415 break;
416 case DBGCVAR_TYPE_HC_FAR:
417 pResult->u.HCFar.off= ~pResult->u.HCFar.off;
418 break;
419 case DBGCVAR_TYPE_HC_PHYS:
420 pResult->u.HCPhys = ~pResult->u.HCPhys;
421 break;
422 case DBGCVAR_TYPE_NUMBER:
423 pResult->u.u64Number = ~pResult->u.u64Number;
424 break;
425
426 case DBGCVAR_TYPE_UNKNOWN:
427 case DBGCVAR_TYPE_STRING:
428 default:
429 return VERR_PARSE_INCORRECT_ARG_TYPE;
430 }
431 NOREF(pDbgc);
432 return VINF_SUCCESS;
433}
434
435
436/**
437 * Reference variable (unary).
438 *
439 * @returns VINF_SUCCESS on success.
440 * @returns VBox evaluation / parsing error code on failure.
441 * The caller does the bitching.
442 * @param pDbgc Debugger console instance data.
443 * @param pArg The argument.
444 * @param pResult Where to store the result.
445 */
446static DECLCALLBACK(int) dbgcOpVar(PDBGC pDbgc, PCDBGCVAR pArg, PDBGCVAR pResult)
447{
448 LogFlow(("dbgcOpVar: %s\n", pArg->u.pszString));
449
450 /*
451 * Parse sanity.
452 */
453 if (pArg->enmType != DBGCVAR_TYPE_STRING)
454 return VERR_PARSE_INCORRECT_ARG_TYPE;
455
456 /*
457 * Lookup the variable.
458 */
459 const char *pszVar = pArg->u.pszString;
460 for (unsigned iVar = 0; iVar < pDbgc->cVars; iVar++)
461 {
462 if (!strcmp(pszVar, pDbgc->papVars[iVar]->szName))
463 {
464 *pResult = pDbgc->papVars[iVar]->Var;
465 return VINF_SUCCESS;
466 }
467 }
468
469 return VERR_PARSE_VARIABLE_NOT_FOUND;
470}
471
472
473/**
474 * Reference register (unary).
475 *
476 * @returns VINF_SUCCESS on success.
477 * @returns VBox evaluation / parsing error code on failure.
478 * The caller does the bitching.
479 * @param pDbgc Debugger console instance data.
480 * @param pArg The argument.
481 * @param pResult Where to store the result.
482 */
483static DECLCALLBACK(int) dbgcOpRegister(PDBGC pDbgc, PCDBGCVAR pArg, PDBGCVAR pResult)
484{
485 LogFlow(("dbgcOpRegister: %s\n", pArg->u.pszString));
486
487 /*
488 * Parse sanity.
489 */
490 if (pArg->enmType != DBGCVAR_TYPE_STRING)
491 return VERR_PARSE_INCORRECT_ARG_TYPE;
492
493 /*
494 * Get the register.
495 */
496 /// @todo DBGFR3RegByName();
497 return VERR_NOT_IMPLEMENTED;
498
499}
500
501
502/**
503 * Flat address (unary).
504 *
505 * @returns VINF_SUCCESS on success.
506 * @returns VBox evaluation / parsing error code on failure.
507 * The caller does the bitching.
508 * @param pDbgc Debugger console instance data.
509 * @param pArg The argument.
510 * @param pResult Where to store the result.
511 */
512DECLCALLBACK(int) dbgcOpAddrFlat(PDBGC pDbgc, PCDBGCVAR pArg, PDBGCVAR pResult)
513{
514 LogFlow(("dbgcOpAddrFlat\n"));
515 int rc;
516 *pResult = *pArg;
517
518 switch (pArg->enmType)
519 {
520 case DBGCVAR_TYPE_GC_FLAT:
521 return VINF_SUCCESS;
522
523 case DBGCVAR_TYPE_GC_FAR:
524 {
525 Assert(pDbgc->pVM);
526 DBGFADDRESS Address;
527 rc = DBGFR3AddrFromSelOff(pDbgc->pVM, pDbgc->idCpu, &Address, pArg->u.GCFar.sel, pArg->u.GCFar.off);
528 if (RT_SUCCESS(rc))
529 {
530 pResult->enmType = DBGCVAR_TYPE_GC_FLAT;
531 pResult->u.GCFlat = Address.FlatPtr;
532 return VINF_SUCCESS;
533 }
534 return VERR_PARSE_CONVERSION_FAILED;
535 }
536
537 case DBGCVAR_TYPE_GC_PHYS:
538 //rc = MMR3PhysGCPhys2GCVirtEx(pDbgc->pVM, pResult->u.GCPhys, ..., &pResult->u.GCFlat); - yea, sure.
539 return VERR_PARSE_INCORRECT_ARG_TYPE;
540
541 case DBGCVAR_TYPE_HC_FLAT:
542 return VINF_SUCCESS;
543
544 case DBGCVAR_TYPE_HC_FAR:
545 return VERR_PARSE_INCORRECT_ARG_TYPE;
546
547 case DBGCVAR_TYPE_HC_PHYS:
548 Assert(pDbgc->pVM);
549 pResult->enmType = DBGCVAR_TYPE_HC_FLAT;
550 rc = MMR3HCPhys2HCVirt(pDbgc->pVM, pResult->u.HCPhys, &pResult->u.pvHCFlat);
551 if (RT_SUCCESS(rc))
552 return VINF_SUCCESS;
553 return VERR_PARSE_CONVERSION_FAILED;
554
555 case DBGCVAR_TYPE_NUMBER:
556 pResult->enmType = DBGCVAR_TYPE_GC_FLAT;
557 pResult->u.GCFlat = (RTGCPTR)pResult->u.u64Number;
558 return VINF_SUCCESS;
559
560 case DBGCVAR_TYPE_STRING:
561 return dbgcSymbolGet(pDbgc, pArg->u.pszString, DBGCVAR_TYPE_GC_FLAT, pResult);
562
563 case DBGCVAR_TYPE_UNKNOWN:
564 default:
565 return VERR_PARSE_INCORRECT_ARG_TYPE;
566 }
567}
568
569
570/**
571 * Physical address (unary).
572 *
573 * @returns VINF_SUCCESS on success.
574 * @returns VBox evaluation / parsing error code on failure.
575 * The caller does the bitching.
576 * @param pDbgc Debugger console instance data.
577 * @param pArg The argument.
578 * @param pResult Where to store the result.
579 */
580DECLCALLBACK(int) dbgcOpAddrPhys(PDBGC pDbgc, PCDBGCVAR pArg, PDBGCVAR pResult)
581{
582 LogFlow(("dbgcOpAddrPhys\n"));
583 int rc;
584 DBGFADDRESS Address;
585
586 *pResult = *pArg;
587 switch (pArg->enmType)
588 {
589 case DBGCVAR_TYPE_GC_FLAT:
590 Assert(pDbgc->pVM);
591 pResult->enmType = DBGCVAR_TYPE_GC_PHYS;
592 rc = DBGFR3AddrToPhys(pDbgc->pVM, pDbgc->idCpu,
593 DBGFR3AddrFromFlat(pDbgc->pVM, &Address, pArg->u.GCFlat),
594 &pResult->u.GCPhys);
595 if (RT_SUCCESS(rc))
596 return VINF_SUCCESS;
597 return VERR_PARSE_CONVERSION_FAILED;
598
599 case DBGCVAR_TYPE_GC_FAR:
600 Assert(pDbgc->pVM);
601 rc = DBGFR3AddrFromSelOff(pDbgc->pVM, pDbgc->idCpu, &Address, pArg->u.GCFar.sel, pArg->u.GCFar.off);
602 if (RT_SUCCESS(rc))
603 {
604 pResult->enmType = DBGCVAR_TYPE_GC_PHYS;
605 rc = DBGFR3AddrToPhys(pDbgc->pVM, pDbgc->idCpu, &Address, &pResult->u.GCPhys);
606 if (RT_SUCCESS(rc))
607 return VINF_SUCCESS;
608 }
609 return VERR_PARSE_CONVERSION_FAILED;
610
611 case DBGCVAR_TYPE_GC_PHYS:
612 return VINF_SUCCESS;
613
614 case DBGCVAR_TYPE_HC_FLAT:
615 Assert(pDbgc->pVM);
616 pResult->enmType = DBGCVAR_TYPE_GC_PHYS;
617 rc = PGMR3DbgR3Ptr2GCPhys(pDbgc->pVM, pArg->u.pvHCFlat, &pResult->u.GCPhys);
618 if (RT_SUCCESS(rc))
619 return VINF_SUCCESS;
620 /** @todo more memory types! */
621 return VERR_PARSE_CONVERSION_FAILED;
622
623 case DBGCVAR_TYPE_HC_FAR:
624 return VERR_PARSE_INCORRECT_ARG_TYPE;
625
626 case DBGCVAR_TYPE_HC_PHYS:
627 return VINF_SUCCESS;
628
629 case DBGCVAR_TYPE_NUMBER:
630 pResult->enmType = DBGCVAR_TYPE_GC_PHYS;
631 pResult->u.GCPhys = (RTGCPHYS)pResult->u.u64Number;
632 return VINF_SUCCESS;
633
634 case DBGCVAR_TYPE_STRING:
635 return dbgcSymbolGet(pDbgc, pArg->u.pszString, DBGCVAR_TYPE_GC_PHYS, pResult);
636
637 case DBGCVAR_TYPE_UNKNOWN:
638 default:
639 return VERR_PARSE_INCORRECT_ARG_TYPE;
640 }
641 return VINF_SUCCESS;
642}
643
644
645/**
646 * Physical host address (unary).
647 *
648 * @returns VINF_SUCCESS on success.
649 * @returns VBox evaluation / parsing error code on failure.
650 * The caller does the bitching.
651 * @param pDbgc Debugger console instance data.
652 * @param pArg The argument.
653 * @param pResult Where to store the result.
654 */
655DECLCALLBACK(int) dbgcOpAddrHostPhys(PDBGC pDbgc, PCDBGCVAR pArg, PDBGCVAR pResult)
656{
657 LogFlow(("dbgcOpAddrPhys\n"));
658 DBGFADDRESS Address;
659 int rc;
660
661 *pResult = *pArg;
662 switch (pArg->enmType)
663 {
664 case DBGCVAR_TYPE_GC_FLAT:
665 Assert(pDbgc->pVM);
666 pResult->enmType = DBGCVAR_TYPE_HC_PHYS;
667 rc = DBGFR3AddrToHostPhys(pDbgc->pVM, pDbgc->idCpu,
668 DBGFR3AddrFromFlat(pDbgc->pVM, &Address, pArg->u.GCFlat),
669 &pResult->u.GCPhys);
670 if (RT_SUCCESS(rc))
671 return VINF_SUCCESS;
672 return VERR_PARSE_CONVERSION_FAILED;
673
674 case DBGCVAR_TYPE_GC_FAR:
675 {
676 Assert(pDbgc->pVM);
677 rc = DBGFR3AddrFromSelOff(pDbgc->pVM, pDbgc->idCpu, &Address, pArg->u.GCFar.sel, pArg->u.GCFar.off);
678 if (RT_SUCCESS(rc))
679 {
680 pResult->enmType = DBGCVAR_TYPE_HC_PHYS;
681 rc = DBGFR3AddrToHostPhys(pDbgc->pVM, pDbgc->idCpu, &Address, &pResult->u.GCPhys);
682 if (RT_SUCCESS(rc))
683 return VINF_SUCCESS;
684 }
685 return VERR_PARSE_CONVERSION_FAILED;
686 }
687
688 case DBGCVAR_TYPE_GC_PHYS:
689 Assert(pDbgc->pVM);
690 pResult->enmType = DBGCVAR_TYPE_HC_PHYS;
691 rc = DBGFR3AddrToHostPhys(pDbgc->pVM, pDbgc->idCpu,
692 DBGFR3AddrFromPhys(pDbgc->pVM, &Address, pArg->u.GCPhys),
693 &pResult->u.GCPhys);
694 if (RT_SUCCESS(rc))
695 return VINF_SUCCESS;
696 return VERR_PARSE_CONVERSION_FAILED;
697
698 case DBGCVAR_TYPE_HC_FLAT:
699 Assert(pDbgc->pVM);
700 pResult->enmType = DBGCVAR_TYPE_HC_PHYS;
701 rc = PGMR3DbgR3Ptr2HCPhys(pDbgc->pVM, pArg->u.pvHCFlat, &pResult->u.HCPhys);
702 if (RT_SUCCESS(rc))
703 return VINF_SUCCESS;
704 /** @todo more memory types! */
705 return VERR_PARSE_CONVERSION_FAILED;
706
707 case DBGCVAR_TYPE_HC_FAR:
708 return VERR_PARSE_INCORRECT_ARG_TYPE;
709
710 case DBGCVAR_TYPE_HC_PHYS:
711 return VINF_SUCCESS;
712
713 case DBGCVAR_TYPE_NUMBER:
714 pResult->enmType = DBGCVAR_TYPE_HC_PHYS;
715 pResult->u.HCPhys = (RTGCPHYS)pResult->u.u64Number;
716 return VINF_SUCCESS;
717
718 case DBGCVAR_TYPE_STRING:
719 return dbgcSymbolGet(pDbgc, pArg->u.pszString, DBGCVAR_TYPE_HC_PHYS, pResult);
720
721 case DBGCVAR_TYPE_UNKNOWN:
722 default:
723 return VERR_PARSE_INCORRECT_ARG_TYPE;
724 }
725 return VINF_SUCCESS;
726}
727
728
729/**
730 * Host address (unary).
731 *
732 * @returns VINF_SUCCESS on success.
733 * @returns VBox evaluation / parsing error code on failure.
734 * The caller does the bitching.
735 * @param pDbgc Debugger console instance data.
736 * @param pArg The argument.
737 * @param pResult Where to store the result.
738 */
739DECLCALLBACK(int) dbgcOpAddrHost(PDBGC pDbgc, PCDBGCVAR pArg, PDBGCVAR pResult)
740{
741 LogFlow(("dbgcOpAddrHost\n"));
742 int rc;
743 DBGFADDRESS Address;
744
745 *pResult = *pArg;
746 switch (pArg->enmType)
747 {
748 case DBGCVAR_TYPE_GC_FLAT:
749 Assert(pDbgc->pVM);
750 pResult->enmType = DBGCVAR_TYPE_HC_FLAT;
751 rc = DBGFR3AddrToVolatileR3Ptr(pDbgc->pVM, pDbgc->idCpu,
752 DBGFR3AddrFromFlat(pDbgc->pVM, &Address, pArg->u.GCFlat),
753 false /*fReadOnly */,
754 &pResult->u.pvHCFlat);
755 if (RT_SUCCESS(rc))
756 return VINF_SUCCESS;
757 return VERR_PARSE_CONVERSION_FAILED;
758
759 case DBGCVAR_TYPE_GC_FAR:
760 Assert(pDbgc->pVM);
761 rc = DBGFR3AddrFromSelOff(pDbgc->pVM, pDbgc->idCpu, &Address, pArg->u.GCFar.sel, pArg->u.GCFar.off);
762 if (RT_SUCCESS(rc))
763 {
764 pResult->enmType = DBGCVAR_TYPE_HC_FLAT;
765 rc = DBGFR3AddrToVolatileR3Ptr(pDbgc->pVM, pDbgc->idCpu, &Address,
766 false /*fReadOnly*/, &pResult->u.pvHCFlat);
767 if (RT_SUCCESS(rc))
768 return VINF_SUCCESS;
769 }
770 return VERR_PARSE_CONVERSION_FAILED;
771
772 case DBGCVAR_TYPE_GC_PHYS:
773 Assert(pDbgc->pVM);
774 pResult->enmType = DBGCVAR_TYPE_HC_FLAT;
775 rc = DBGFR3AddrToVolatileR3Ptr(pDbgc->pVM, pDbgc->idCpu,
776 DBGFR3AddrFromPhys(pDbgc->pVM, &Address, pArg->u.GCPhys),
777 false /*fReadOnly */,
778 &pResult->u.pvHCFlat);
779 if (RT_SUCCESS(rc))
780 return VINF_SUCCESS;
781 return VERR_PARSE_CONVERSION_FAILED;
782
783 case DBGCVAR_TYPE_HC_FLAT:
784 return VINF_SUCCESS;
785
786 case DBGCVAR_TYPE_HC_FAR:
787 case DBGCVAR_TYPE_HC_PHYS:
788 /** @todo !*/
789 return VERR_PARSE_CONVERSION_FAILED;
790
791 case DBGCVAR_TYPE_NUMBER:
792 pResult->enmType = DBGCVAR_TYPE_HC_FLAT;
793 pResult->u.pvHCFlat = (void *)(uintptr_t)pResult->u.u64Number;
794 return VINF_SUCCESS;
795
796 case DBGCVAR_TYPE_STRING:
797 return dbgcSymbolGet(pDbgc, pArg->u.pszString, DBGCVAR_TYPE_HC_FLAT, pResult);
798
799 case DBGCVAR_TYPE_UNKNOWN:
800 default:
801 return VERR_PARSE_INCORRECT_ARG_TYPE;
802 }
803}
804
805
806/**
807 * Bitwise not (unary).
808 *
809 * @returns VINF_SUCCESS on success.
810 * @returns VBox evaluation / parsing error code on failure.
811 * The caller does the bitching.
812 * @param pDbgc Debugger console instance data.
813 * @param pArg The argument.
814 * @param pResult Where to store the result.
815 */
816static DECLCALLBACK(int) dbgcOpAddrFar(PDBGC pDbgc, PCDBGCVAR pArg1, PCDBGCVAR pArg2, PDBGCVAR pResult)
817{
818 LogFlow(("dbgcOpAddrFar\n"));
819 int rc;
820
821 switch (pArg1->enmType)
822 {
823 case DBGCVAR_TYPE_STRING:
824 rc = dbgcSymbolGet(pDbgc, pArg1->u.pszString, DBGCVAR_TYPE_NUMBER, pResult);
825 if (RT_FAILURE(rc))
826 return rc;
827 break;
828 case DBGCVAR_TYPE_NUMBER:
829 *pResult = *pArg1;
830 break;
831
832 case DBGCVAR_TYPE_GC_FLAT:
833 case DBGCVAR_TYPE_GC_FAR:
834 case DBGCVAR_TYPE_GC_PHYS:
835 case DBGCVAR_TYPE_HC_FLAT:
836 case DBGCVAR_TYPE_HC_FAR:
837 case DBGCVAR_TYPE_HC_PHYS:
838 case DBGCVAR_TYPE_UNKNOWN:
839 default:
840 return VERR_PARSE_INCORRECT_ARG_TYPE;
841 }
842 pResult->u.GCFar.sel = (RTSEL)pResult->u.u64Number;
843
844 /* common code for the two types we support. */
845 switch (pArg2->enmType)
846 {
847 case DBGCVAR_TYPE_GC_FLAT:
848 pResult->u.GCFar.off = pArg2->u.GCFlat;
849 pResult->enmType = DBGCVAR_TYPE_GC_FAR;
850 break;
851
852 case DBGCVAR_TYPE_HC_FLAT:
853 pResult->u.HCFar.off = pArg2->u.GCFlat;
854 pResult->enmType = DBGCVAR_TYPE_GC_FAR;
855 break;
856
857 case DBGCVAR_TYPE_NUMBER:
858 pResult->u.GCFar.off = (RTGCPTR)pArg2->u.u64Number;
859 pResult->enmType = DBGCVAR_TYPE_GC_FAR;
860 break;
861
862 case DBGCVAR_TYPE_STRING:
863 {
864 DBGCVAR Var;
865 rc = dbgcSymbolGet(pDbgc, pArg2->u.pszString, DBGCVAR_TYPE_NUMBER, &Var);
866 if (RT_FAILURE(rc))
867 return rc;
868 pResult->u.GCFar.off = (RTGCPTR)Var.u.u64Number;
869 pResult->enmType = DBGCVAR_TYPE_GC_FAR;
870 break;
871 }
872
873 case DBGCVAR_TYPE_GC_FAR:
874 case DBGCVAR_TYPE_GC_PHYS:
875 case DBGCVAR_TYPE_HC_FAR:
876 case DBGCVAR_TYPE_HC_PHYS:
877 case DBGCVAR_TYPE_UNKNOWN:
878 default:
879 return VERR_PARSE_INCORRECT_ARG_TYPE;
880 }
881 return VINF_SUCCESS;
882
883}
884
885
886/**
887 * Multiplication operator (binary).
888 *
889 * @returns VINF_SUCCESS on success.
890 * @returns VBox evaluation / parsing error code on failure.
891 * The caller does the bitching.
892 * @param pDbgc Debugger console instance data.
893 * @param pArg1 The first argument.
894 * @param pArg2 The 2nd argument.
895 * @param pResult Where to store the result.
896 */
897static DECLCALLBACK(int) dbgcOpMult(PDBGC pDbgc, PCDBGCVAR pArg1, PCDBGCVAR pArg2, PDBGCVAR pResult)
898{
899 LogFlow(("dbgcOpMult\n"));
900 DBGC_GEN_ARIT_POINTER_TO_THE_LEFT(pArg1, pArg2);
901 DBGC_GEN_ARIT_BINARY_OP(pDbgc, pArg1, pArg2, pResult, *, false);
902}
903
904
905/**
906 * Division operator (binary).
907 *
908 * @returns VINF_SUCCESS on success.
909 * @returns VBox evaluation / parsing error code on failure.
910 * The caller does the bitching.
911 * @param pDbgc Debugger console instance data.
912 * @param pArg1 The first argument.
913 * @param pArg2 The 2nd argument.
914 * @param pResult Where to store the result.
915 */
916static DECLCALLBACK(int) dbgcOpDiv(PDBGC pDbgc, PCDBGCVAR pArg1, PCDBGCVAR pArg2, PDBGCVAR pResult)
917{
918 LogFlow(("dbgcOpDiv\n"));
919 DBGC_GEN_ARIT_BINARY_OP(pDbgc, pArg1, pArg2, pResult, /, true);
920}
921
922
923/**
924 * Modulus operator (binary).
925 *
926 * @returns VINF_SUCCESS on success.
927 * @returns VBox evaluation / parsing error code on failure.
928 * The caller does the bitching.
929 * @param pDbgc Debugger console instance data.
930 * @param pArg1 The first argument.
931 * @param pArg2 The 2nd argument.
932 * @param pResult Where to store the result.
933 */
934static DECLCALLBACK(int) dbgcOpMod(PDBGC pDbgc, PCDBGCVAR pArg1, PCDBGCVAR pArg2, PDBGCVAR pResult)
935{
936 LogFlow(("dbgcOpMod\n"));
937 DBGC_GEN_ARIT_BINARY_OP(pDbgc, pArg1, pArg2, pResult, %, false);
938}
939
940
941/**
942 * Addition operator (binary).
943 *
944 * @returns VINF_SUCCESS on success.
945 * @returns VBox evaluation / parsing error code on failure.
946 * The caller does the bitching.
947 * @param pDbgc Debugger console instance data.
948 * @param pArg1 The first argument.
949 * @param pArg2 The 2nd argument.
950 * @param pResult Where to store the result.
951 */
952static DECLCALLBACK(int) dbgcOpAdd(PDBGC pDbgc, PCDBGCVAR pArg1, PCDBGCVAR pArg2, PDBGCVAR pResult)
953{
954 LogFlow(("dbgcOpAdd\n"));
955
956 /*
957 * An addition operation will return (when possible) the left side type in the
958 * expression. We make an omission for numbers, where we'll take the right side
959 * type instead. An expression where only the left hand side is a string we'll
960 * use the right hand type assuming that the string is a symbol.
961 */
962 if ( (pArg1->enmType == DBGCVAR_TYPE_NUMBER && pArg2->enmType != DBGCVAR_TYPE_STRING)
963 || (pArg1->enmType == DBGCVAR_TYPE_STRING && pArg2->enmType != DBGCVAR_TYPE_STRING))
964 {
965 PCDBGCVAR pTmp = pArg2;
966 pArg2 = pArg1;
967 pArg1 = pTmp;
968 }
969 DBGCVAR Sym1, Sym2;
970 if (pArg1->enmType == DBGCVAR_TYPE_STRING)
971 {
972 int rc = dbgcSymbolGet(pDbgc, pArg1->u.pszString, DBGCVAR_TYPE_ANY, &Sym1);
973 if (RT_FAILURE(rc))
974 return rc;
975 pArg1 = &Sym1;
976
977 rc = dbgcSymbolGet(pDbgc, pArg2->u.pszString, DBGCVAR_TYPE_ANY, &Sym2);
978 if (RT_FAILURE(rc))
979 return rc;
980 pArg2 = &Sym2;
981 }
982
983 int rc;
984 DBGCVAR Var;
985 DBGCVAR Var2;
986 switch (pArg1->enmType)
987 {
988 /*
989 * GC Flat
990 */
991 case DBGCVAR_TYPE_GC_FLAT:
992 switch (pArg2->enmType)
993 {
994 case DBGCVAR_TYPE_HC_FLAT:
995 case DBGCVAR_TYPE_HC_FAR:
996 case DBGCVAR_TYPE_HC_PHYS:
997 return VERR_PARSE_INVALID_OPERATION;
998 default:
999 *pResult = *pArg1;
1000 rc = dbgcOpAddrFlat(pDbgc, pArg2, &Var);
1001 if (RT_FAILURE(rc))
1002 return rc;
1003 pResult->u.GCFlat += pArg2->u.GCFlat;
1004 break;
1005 }
1006 break;
1007
1008 /*
1009 * GC Far
1010 */
1011 case DBGCVAR_TYPE_GC_FAR:
1012 switch (pArg2->enmType)
1013 {
1014 case DBGCVAR_TYPE_HC_FLAT:
1015 case DBGCVAR_TYPE_HC_FAR:
1016 case DBGCVAR_TYPE_HC_PHYS:
1017 return VERR_PARSE_INVALID_OPERATION;
1018 case DBGCVAR_TYPE_NUMBER:
1019 *pResult = *pArg1;
1020 pResult->u.GCFar.off += (RTGCPTR)pArg2->u.u64Number;
1021 break;
1022 default:
1023 rc = dbgcOpAddrFlat(pDbgc, pArg1, pResult);
1024 if (RT_FAILURE(rc))
1025 return rc;
1026 rc = dbgcOpAddrFlat(pDbgc, pArg2, &Var);
1027 if (RT_FAILURE(rc))
1028 return rc;
1029 pResult->u.GCFlat += pArg2->u.GCFlat;
1030 break;
1031 }
1032 break;
1033
1034 /*
1035 * GC Phys
1036 */
1037 case DBGCVAR_TYPE_GC_PHYS:
1038 switch (pArg2->enmType)
1039 {
1040 case DBGCVAR_TYPE_HC_FLAT:
1041 case DBGCVAR_TYPE_HC_FAR:
1042 case DBGCVAR_TYPE_HC_PHYS:
1043 return VERR_PARSE_INVALID_OPERATION;
1044 default:
1045 *pResult = *pArg1;
1046 rc = dbgcOpAddrPhys(pDbgc, pArg2, &Var);
1047 if (RT_FAILURE(rc))
1048 return rc;
1049 if (Var.enmType != DBGCVAR_TYPE_GC_PHYS)
1050 return VERR_PARSE_INVALID_OPERATION;
1051 pResult->u.GCPhys += Var.u.GCPhys;
1052 break;
1053 }
1054 break;
1055
1056 /*
1057 * HC Flat
1058 */
1059 case DBGCVAR_TYPE_HC_FLAT:
1060 *pResult = *pArg1;
1061 rc = dbgcOpAddrHost(pDbgc, pArg2, &Var2);
1062 if (RT_FAILURE(rc))
1063 return rc;
1064 rc = dbgcOpAddrFlat(pDbgc, &Var2, &Var);
1065 if (RT_FAILURE(rc))
1066 return rc;
1067 pResult->u.pvHCFlat = (char *)pResult->u.pvHCFlat + (uintptr_t)Var.u.pvHCFlat;
1068 break;
1069
1070 /*
1071 * HC Far
1072 */
1073 case DBGCVAR_TYPE_HC_FAR:
1074 switch (pArg2->enmType)
1075 {
1076 case DBGCVAR_TYPE_NUMBER:
1077 *pResult = *pArg1;
1078 pResult->u.HCFar.off += (uintptr_t)pArg2->u.u64Number;
1079 break;
1080
1081 default:
1082 rc = dbgcOpAddrFlat(pDbgc, pArg1, pResult);
1083 if (RT_FAILURE(rc))
1084 return rc;
1085 rc = dbgcOpAddrHost(pDbgc, pArg2, &Var2);
1086 if (RT_FAILURE(rc))
1087 return rc;
1088 rc = dbgcOpAddrFlat(pDbgc, &Var2, &Var);
1089 if (RT_FAILURE(rc))
1090 return rc;
1091 pResult->u.pvHCFlat = (char *)pResult->u.pvHCFlat + (uintptr_t)Var.u.pvHCFlat;
1092 break;
1093 }
1094 break;
1095
1096 /*
1097 * HC Phys
1098 */
1099 case DBGCVAR_TYPE_HC_PHYS:
1100 *pResult = *pArg1;
1101 rc = dbgcOpAddrHostPhys(pDbgc, pArg2, &Var);
1102 if (RT_FAILURE(rc))
1103 return rc;
1104 pResult->u.HCPhys += Var.u.HCPhys;
1105 break;
1106
1107 /*
1108 * Numbers (see start of function)
1109 */
1110 case DBGCVAR_TYPE_NUMBER:
1111 *pResult = *pArg1;
1112 switch (pArg2->enmType)
1113 {
1114 case DBGCVAR_TYPE_SYMBOL:
1115 case DBGCVAR_TYPE_STRING:
1116 rc = dbgcSymbolGet(pDbgc, pArg2->u.pszString, DBGCVAR_TYPE_NUMBER, &Var);
1117 if (RT_FAILURE(rc))
1118 return rc;
1119 case DBGCVAR_TYPE_NUMBER:
1120 pResult->u.u64Number += pArg2->u.u64Number;
1121 break;
1122 default:
1123 return VERR_PARSE_INVALID_OPERATION;
1124 }
1125 break;
1126
1127 default:
1128 return VERR_PARSE_INVALID_OPERATION;
1129
1130 }
1131 return VINF_SUCCESS;
1132}
1133
1134
1135/**
1136 * Subtraction operator (binary).
1137 *
1138 * @returns VINF_SUCCESS on success.
1139 * @returns VBox evaluation / parsing error code on failure.
1140 * The caller does the bitching.
1141 * @param pDbgc Debugger console instance data.
1142 * @param pArg1 The first argument.
1143 * @param pArg2 The 2nd argument.
1144 * @param pResult Where to store the result.
1145 */
1146static DECLCALLBACK(int) dbgcOpSub(PDBGC pDbgc, PCDBGCVAR pArg1, PCDBGCVAR pArg2, PDBGCVAR pResult)
1147{
1148 LogFlow(("dbgcOpSub\n"));
1149
1150 /*
1151 * An subtraction operation will return the left side type in the expression.
1152 * However, if the left hand side is a number and the right hand a pointer of
1153 * some kind we'll convert the left hand side to the same type as the right hand.
1154 * Any strings will be attempted resolved as symbols.
1155 */
1156 DBGCVAR Sym1, Sym2;
1157 if ( pArg2->enmType == DBGCVAR_TYPE_STRING
1158 && ( pArg1->enmType == DBGCVAR_TYPE_NUMBER
1159 || pArg1->enmType == DBGCVAR_TYPE_STRING))
1160 {
1161 int rc = dbgcSymbolGet(pDbgc, pArg2->u.pszString, DBGCVAR_TYPE_ANY, &Sym2);
1162 if (RT_FAILURE(rc))
1163 return rc;
1164 pArg2 = &Sym2;
1165 }
1166
1167 if (pArg1->enmType == DBGCVAR_TYPE_STRING)
1168 {
1169 DBGCVARTYPE enmType;
1170 switch (pArg2->enmType)
1171 {
1172 case DBGCVAR_TYPE_NUMBER:
1173 enmType = DBGCVAR_TYPE_ANY;
1174 break;
1175 case DBGCVAR_TYPE_GC_FLAT:
1176 case DBGCVAR_TYPE_GC_PHYS:
1177 case DBGCVAR_TYPE_HC_FLAT:
1178 case DBGCVAR_TYPE_HC_PHYS:
1179 enmType = pArg2->enmType;
1180 break;
1181 case DBGCVAR_TYPE_GC_FAR:
1182 enmType = DBGCVAR_TYPE_GC_FLAT;
1183 break;
1184 case DBGCVAR_TYPE_HC_FAR:
1185 enmType = DBGCVAR_TYPE_HC_FLAT;
1186 break;
1187
1188 default:
1189 case DBGCVAR_TYPE_STRING:
1190 AssertMsgFailed(("Can't happen\n"));
1191 enmType = DBGCVAR_TYPE_STRING;
1192 break;
1193 }
1194 if (enmType != DBGCVAR_TYPE_STRING)
1195 {
1196 int rc = dbgcSymbolGet(pDbgc, pArg1->u.pszString, DBGCVAR_TYPE_ANY, &Sym1);
1197 if (RT_FAILURE(rc))
1198 return rc;
1199 pArg1 = &Sym1;
1200 }
1201 }
1202 else if (pArg1->enmType == DBGCVAR_TYPE_NUMBER)
1203 {
1204 PFNDBGCOPUNARY pOp = NULL;
1205 switch (pArg2->enmType)
1206 {
1207 case DBGCVAR_TYPE_GC_FAR:
1208 case DBGCVAR_TYPE_GC_FLAT:
1209 pOp = dbgcOpAddrFlat;
1210 break;
1211 case DBGCVAR_TYPE_GC_PHYS:
1212 pOp = dbgcOpAddrPhys;
1213 break;
1214 case DBGCVAR_TYPE_HC_FAR:
1215 case DBGCVAR_TYPE_HC_FLAT:
1216 pOp = dbgcOpAddrHost;
1217 break;
1218 case DBGCVAR_TYPE_HC_PHYS:
1219 pOp = dbgcOpAddrHostPhys;
1220 break;
1221 case DBGCVAR_TYPE_NUMBER:
1222 break;
1223 default:
1224 case DBGCVAR_TYPE_STRING:
1225 AssertMsgFailed(("Can't happen\n"));
1226 break;
1227 }
1228 if (pOp)
1229 {
1230 int rc = pOp(pDbgc, pArg1, &Sym1);
1231 if (RT_FAILURE(rc))
1232 return rc;
1233 pArg1 = &Sym1;
1234 }
1235 }
1236
1237
1238 /*
1239 * Normal processing.
1240 */
1241 int rc;
1242 DBGCVAR Var;
1243 DBGCVAR Var2;
1244 switch (pArg1->enmType)
1245 {
1246 /*
1247 * GC Flat
1248 */
1249 case DBGCVAR_TYPE_GC_FLAT:
1250 switch (pArg2->enmType)
1251 {
1252 case DBGCVAR_TYPE_HC_FLAT:
1253 case DBGCVAR_TYPE_HC_FAR:
1254 case DBGCVAR_TYPE_HC_PHYS:
1255 return VERR_PARSE_INVALID_OPERATION;
1256 default:
1257 *pResult = *pArg1;
1258 rc = dbgcOpAddrFlat(pDbgc, pArg2, &Var);
1259 if (RT_FAILURE(rc))
1260 return rc;
1261 pResult->u.GCFlat -= pArg2->u.GCFlat;
1262 break;
1263 }
1264 break;
1265
1266 /*
1267 * GC Far
1268 */
1269 case DBGCVAR_TYPE_GC_FAR:
1270 switch (pArg2->enmType)
1271 {
1272 case DBGCVAR_TYPE_HC_FLAT:
1273 case DBGCVAR_TYPE_HC_FAR:
1274 case DBGCVAR_TYPE_HC_PHYS:
1275 return VERR_PARSE_INVALID_OPERATION;
1276 case DBGCVAR_TYPE_NUMBER:
1277 *pResult = *pArg1;
1278 pResult->u.GCFar.off -= (RTGCPTR)pArg2->u.u64Number;
1279 break;
1280 default:
1281 rc = dbgcOpAddrFlat(pDbgc, pArg1, pResult);
1282 if (RT_FAILURE(rc))
1283 return rc;
1284 rc = dbgcOpAddrFlat(pDbgc, pArg2, &Var);
1285 if (RT_FAILURE(rc))
1286 return rc;
1287 pResult->u.GCFlat -= pArg2->u.GCFlat;
1288 break;
1289 }
1290 break;
1291
1292 /*
1293 * GC Phys
1294 */
1295 case DBGCVAR_TYPE_GC_PHYS:
1296 switch (pArg2->enmType)
1297 {
1298 case DBGCVAR_TYPE_HC_FLAT:
1299 case DBGCVAR_TYPE_HC_FAR:
1300 case DBGCVAR_TYPE_HC_PHYS:
1301 return VERR_PARSE_INVALID_OPERATION;
1302 default:
1303 *pResult = *pArg1;
1304 rc = dbgcOpAddrPhys(pDbgc, pArg2, &Var);
1305 if (RT_FAILURE(rc))
1306 return rc;
1307 if (Var.enmType != DBGCVAR_TYPE_GC_PHYS)
1308 return VERR_PARSE_INVALID_OPERATION;
1309 pResult->u.GCPhys -= Var.u.GCPhys;
1310 break;
1311 }
1312 break;
1313
1314 /*
1315 * HC Flat
1316 */
1317 case DBGCVAR_TYPE_HC_FLAT:
1318 *pResult = *pArg1;
1319 rc = dbgcOpAddrHost(pDbgc, pArg2, &Var2);
1320 if (RT_FAILURE(rc))
1321 return rc;
1322 rc = dbgcOpAddrFlat(pDbgc, &Var2, &Var);
1323 if (RT_FAILURE(rc))
1324 return rc;
1325 pResult->u.pvHCFlat = (char *)pResult->u.pvHCFlat - (uintptr_t)Var.u.pvHCFlat;
1326 break;
1327
1328 /*
1329 * HC Far
1330 */
1331 case DBGCVAR_TYPE_HC_FAR:
1332 switch (pArg2->enmType)
1333 {
1334 case DBGCVAR_TYPE_NUMBER:
1335 *pResult = *pArg1;
1336 pResult->u.HCFar.off -= (uintptr_t)pArg2->u.u64Number;
1337 break;
1338
1339 default:
1340 rc = dbgcOpAddrFlat(pDbgc, pArg1, pResult);
1341 if (RT_FAILURE(rc))
1342 return rc;
1343 rc = dbgcOpAddrHost(pDbgc, pArg2, &Var2);
1344 if (RT_FAILURE(rc))
1345 return rc;
1346 rc = dbgcOpAddrFlat(pDbgc, &Var2, &Var);
1347 if (RT_FAILURE(rc))
1348 return rc;
1349 pResult->u.pvHCFlat = (char *)pResult->u.pvHCFlat - (uintptr_t)Var.u.pvHCFlat;
1350 break;
1351 }
1352 break;
1353
1354 /*
1355 * HC Phys
1356 */
1357 case DBGCVAR_TYPE_HC_PHYS:
1358 *pResult = *pArg1;
1359 rc = dbgcOpAddrHostPhys(pDbgc, pArg2, &Var);
1360 if (RT_FAILURE(rc))
1361 return rc;
1362 pResult->u.HCPhys -= Var.u.HCPhys;
1363 break;
1364
1365 /*
1366 * Numbers (see start of function)
1367 */
1368 case DBGCVAR_TYPE_NUMBER:
1369 *pResult = *pArg1;
1370 switch (pArg2->enmType)
1371 {
1372 case DBGCVAR_TYPE_SYMBOL:
1373 case DBGCVAR_TYPE_STRING:
1374 rc = dbgcSymbolGet(pDbgc, pArg2->u.pszString, DBGCVAR_TYPE_NUMBER, &Var);
1375 if (RT_FAILURE(rc))
1376 return rc;
1377 case DBGCVAR_TYPE_NUMBER:
1378 pResult->u.u64Number -= pArg2->u.u64Number;
1379 break;
1380 default:
1381 return VERR_PARSE_INVALID_OPERATION;
1382 }
1383 break;
1384
1385 default:
1386 return VERR_PARSE_INVALID_OPERATION;
1387
1388 }
1389 return VINF_SUCCESS;
1390}
1391
1392
1393/**
1394 * Bitwise shift left operator (binary).
1395 *
1396 * @returns VINF_SUCCESS on success.
1397 * @returns VBox evaluation / parsing error code on failure.
1398 * The caller does the bitching.
1399 * @param pDbgc Debugger console instance data.
1400 * @param pArg1 The first argument.
1401 * @param pArg2 The 2nd argument.
1402 * @param pResult Where to store the result.
1403 */
1404static DECLCALLBACK(int) dbgcOpBitwiseShiftLeft(PDBGC pDbgc, PCDBGCVAR pArg1, PCDBGCVAR pArg2, PDBGCVAR pResult)
1405{
1406 LogFlow(("dbgcOpBitwiseShiftLeft\n"));
1407 DBGC_GEN_ARIT_BINARY_OP(pDbgc, pArg1, pArg2, pResult, <<, false);
1408}
1409
1410
1411/**
1412 * Bitwise shift right operator (binary).
1413 *
1414 * @returns VINF_SUCCESS on success.
1415 * @returns VBox evaluation / parsing error code on failure.
1416 * The caller does the bitching.
1417 * @param pDbgc Debugger console instance data.
1418 * @param pArg1 The first argument.
1419 * @param pArg2 The 2nd argument.
1420 * @param pResult Where to store the result.
1421 */
1422static DECLCALLBACK(int) dbgcOpBitwiseShiftRight(PDBGC pDbgc, PCDBGCVAR pArg1, PCDBGCVAR pArg2, PDBGCVAR pResult)
1423{
1424 LogFlow(("dbgcOpBitwiseShiftRight\n"));
1425 DBGC_GEN_ARIT_BINARY_OP(pDbgc, pArg1, pArg2, pResult, >>, false);
1426}
1427
1428
1429/**
1430 * Bitwise and operator (binary).
1431 *
1432 * @returns VINF_SUCCESS on success.
1433 * @returns VBox evaluation / parsing error code on failure.
1434 * The caller does the bitching.
1435 * @param pDbgc Debugger console instance data.
1436 * @param pArg1 The first argument.
1437 * @param pArg2 The 2nd argument.
1438 * @param pResult Where to store the result.
1439 */
1440static DECLCALLBACK(int) dbgcOpBitwiseAnd(PDBGC pDbgc, PCDBGCVAR pArg1, PCDBGCVAR pArg2, PDBGCVAR pResult)
1441{
1442 LogFlow(("dbgcOpBitwiseAnd\n"));
1443 DBGC_GEN_ARIT_POINTER_TO_THE_LEFT(pArg1, pArg2);
1444 DBGC_GEN_ARIT_BINARY_OP(pDbgc, pArg1, pArg2, pResult, &, false);
1445}
1446
1447
1448/**
1449 * Bitwise exclusive or operator (binary).
1450 *
1451 * @returns VINF_SUCCESS on success.
1452 * @returns VBox evaluation / parsing error code on failure.
1453 * The caller does the bitching.
1454 * @param pDbgc Debugger console instance data.
1455 * @param pArg1 The first argument.
1456 * @param pArg2 The 2nd argument.
1457 * @param pResult Where to store the result.
1458 */
1459static DECLCALLBACK(int) dbgcOpBitwiseXor(PDBGC pDbgc, PCDBGCVAR pArg1, PCDBGCVAR pArg2, PDBGCVAR pResult)
1460{
1461 LogFlow(("dbgcOpBitwiseXor\n"));
1462 DBGC_GEN_ARIT_POINTER_TO_THE_LEFT(pArg1, pArg2);
1463 DBGC_GEN_ARIT_BINARY_OP(pDbgc, pArg1, pArg2, pResult, ^, false);
1464}
1465
1466
1467/**
1468 * Bitwise inclusive or operator (binary).
1469 *
1470 * @returns VINF_SUCCESS on success.
1471 * @returns VBox evaluation / parsing error code on failure.
1472 * The caller does the bitching.
1473 * @param pDbgc Debugger console instance data.
1474 * @param pArg1 The first argument.
1475 * @param pArg2 The 2nd argument.
1476 * @param pResult Where to store the result.
1477 */
1478static DECLCALLBACK(int) dbgcOpBitwiseOr(PDBGC pDbgc, PCDBGCVAR pArg1, PCDBGCVAR pArg2, PDBGCVAR pResult)
1479{
1480 LogFlow(("dbgcOpBitwiseOr\n"));
1481 DBGC_GEN_ARIT_POINTER_TO_THE_LEFT(pArg1, pArg2);
1482 DBGC_GEN_ARIT_BINARY_OP(pDbgc, pArg1, pArg2, pResult, |, false);
1483}
1484
1485
1486/**
1487 * Boolean and operator (binary).
1488 *
1489 * @returns VINF_SUCCESS on success.
1490 * @returns VBox evaluation / parsing error code on failure.
1491 * The caller does the bitching.
1492 * @param pDbgc Debugger console instance data.
1493 * @param pArg1 The first argument.
1494 * @param pArg2 The 2nd argument.
1495 * @param pResult Where to store the result.
1496 */
1497static DECLCALLBACK(int) dbgcOpBooleanAnd(PDBGC pDbgc, PCDBGCVAR pArg1, PCDBGCVAR pArg2, PDBGCVAR pResult)
1498{
1499 LogFlow(("dbgcOpBooleanAnd\n"));
1500 /** @todo force numeric return value? */
1501 DBGC_GEN_ARIT_BINARY_OP(pDbgc, pArg1, pArg2, pResult, &&, false);
1502}
1503
1504
1505/**
1506 * Boolean or operator (binary).
1507 *
1508 * @returns VINF_SUCCESS on success.
1509 * @returns VBox evaluation / parsing error code on failure.
1510 * The caller does the bitching.
1511 * @param pDbgc Debugger console instance data.
1512 * @param pArg1 The first argument.
1513 * @param pArg2 The 2nd argument.
1514 * @param pResult Where to store the result.
1515 */
1516static DECLCALLBACK(int) dbgcOpBooleanOr(PDBGC pDbgc, PCDBGCVAR pArg1, PCDBGCVAR pArg2, PDBGCVAR pResult)
1517{
1518 LogFlow(("dbgcOpBooleanOr\n"));
1519 /** @todo force numeric return value? */
1520 DBGC_GEN_ARIT_BINARY_OP(pDbgc, pArg1, pArg2, pResult, ||, false);
1521}
1522
1523
1524/**
1525 * Range to operator (binary).
1526 *
1527 * @returns VINF_SUCCESS on success.
1528 * @returns VBox evaluation / parsing error code on failure.
1529 * The caller does the bitching.
1530 * @param pDbgc Debugger console instance data.
1531 * @param pArg1 The first argument.
1532 * @param pArg2 The 2nd argument.
1533 * @param pResult Where to store the result.
1534 */
1535static DECLCALLBACK(int) dbgcOpRangeLength(PDBGC pDbgc, PCDBGCVAR pArg1, PCDBGCVAR pArg2, PDBGCVAR pResult)
1536{
1537 LogFlow(("dbgcOpRangeLength\n"));
1538
1539 /*
1540 * Make result. Strings needs to be resolved into symbols.
1541 */
1542 if (pArg1->enmType == DBGCVAR_TYPE_STRING)
1543 {
1544 int rc = dbgcSymbolGet(pDbgc, pArg1->u.pszString, DBGCVAR_TYPE_ANY, pResult);
1545 if (RT_FAILURE(rc))
1546 return rc;
1547 }
1548 else
1549 *pResult = *pArg1;
1550
1551 /*
1552 * Convert 2nd argument to element count.
1553 */
1554 pResult->enmRangeType = DBGCVAR_RANGE_ELEMENTS;
1555 switch (pArg2->enmType)
1556 {
1557 case DBGCVAR_TYPE_NUMBER:
1558 pResult->u64Range = pArg2->u.u64Number;
1559 break;
1560
1561 case DBGCVAR_TYPE_STRING:
1562 {
1563 int rc = dbgcSymbolGet(pDbgc, pArg2->u.pszString, DBGCVAR_TYPE_NUMBER, pResult);
1564 if (RT_FAILURE(rc))
1565 return rc;
1566 pResult->u64Range = pArg2->u.u64Number;
1567 break;
1568 }
1569
1570 default:
1571 return VERR_PARSE_INVALID_OPERATION;
1572 }
1573
1574 return VINF_SUCCESS;
1575}
1576
1577
1578/**
1579 * Range to operator (binary).
1580 *
1581 * @returns VINF_SUCCESS on success.
1582 * @returns VBox evaluation / parsing error code on failure.
1583 * The caller does the bitching.
1584 * @param pDbgc Debugger console instance data.
1585 * @param pArg1 The first argument.
1586 * @param pArg2 The 2nd argument.
1587 * @param pResult Where to store the result.
1588 */
1589static DECLCALLBACK(int) dbgcOpRangeLengthBytes(PDBGC pDbgc, PCDBGCVAR pArg1, PCDBGCVAR pArg2, PDBGCVAR pResult)
1590{
1591 LogFlow(("dbgcOpRangeLengthBytes\n"));
1592 int rc = dbgcOpRangeLength(pDbgc, pArg1, pArg2, pResult);
1593 if (RT_SUCCESS(rc))
1594 pResult->enmRangeType = DBGCVAR_RANGE_BYTES;
1595 return rc;
1596}
1597
1598
1599/**
1600 * Range to operator (binary).
1601 *
1602 * @returns VINF_SUCCESS on success.
1603 * @returns VBox evaluation / parsing error code on failure.
1604 * The caller does the bitching.
1605 * @param pDbgc Debugger console instance data.
1606 * @param pArg1 The first argument.
1607 * @param pArg2 The 2nd argument.
1608 * @param pResult Where to store the result.
1609 */
1610static DECLCALLBACK(int) dbgcOpRangeTo(PDBGC pDbgc, PCDBGCVAR pArg1, PCDBGCVAR pArg2, PDBGCVAR pResult)
1611{
1612 LogFlow(("dbgcOpRangeTo\n"));
1613
1614 /*
1615 * Calc number of bytes between the two args.
1616 */
1617 DBGCVAR Diff;
1618 int rc = dbgcOpSub(pDbgc, pArg2, pArg1, &Diff);
1619 if (RT_FAILURE(rc))
1620 return rc;
1621
1622 /*
1623 * Use the diff as the range of Arg1.
1624 */
1625 *pResult = *pArg1;
1626 pResult->enmRangeType = DBGCVAR_RANGE_BYTES;
1627 switch (Diff.enmType)
1628 {
1629 case DBGCVAR_TYPE_GC_FLAT:
1630 pResult->u64Range = (RTGCUINTPTR)Diff.u.GCFlat;
1631 break;
1632 case DBGCVAR_TYPE_GC_PHYS:
1633 pResult->u64Range = Diff.u.GCPhys;
1634 break;
1635 case DBGCVAR_TYPE_HC_FLAT:
1636 pResult->u64Range = (uintptr_t)Diff.u.pvHCFlat;
1637 break;
1638 case DBGCVAR_TYPE_HC_PHYS:
1639 pResult->u64Range = Diff.u.HCPhys;
1640 break;
1641 case DBGCVAR_TYPE_NUMBER:
1642 pResult->u64Range = Diff.u.u64Number;
1643 break;
1644
1645 case DBGCVAR_TYPE_GC_FAR:
1646 case DBGCVAR_TYPE_STRING:
1647 case DBGCVAR_TYPE_HC_FAR:
1648 default:
1649 AssertMsgFailed(("Impossible!\n"));
1650 return VERR_PARSE_INVALID_OPERATION;
1651 }
1652
1653 return VINF_SUCCESS;
1654}
1655
1656
1657/**
1658 * Searches for an operator descriptor which matches the start of
1659 * the expression given us.
1660 *
1661 * @returns Pointer to the operator on success.
1662 * @param pDbgc The debug console instance.
1663 * @param pszExpr Pointer to the expression string which might start with an operator.
1664 * @param fPreferBinary Whether to favour binary or unary operators.
1665 * Caller must assert that it's the desired type! Both types will still
1666 * be returned, this is only for resolving duplicates.
1667 * @param chPrev The previous char. Some operators requires a blank in front of it.
1668 */
1669PCDBGCOP dbgcOperatorLookup(PDBGC pDbgc, const char *pszExpr, bool fPreferBinary, char chPrev)
1670{
1671 PCDBGCOP pOp = NULL;
1672 for (unsigned iOp = 0; iOp < RT_ELEMENTS(g_aOps); iOp++)
1673 {
1674 if ( g_aOps[iOp].szName[0] == pszExpr[0]
1675 && (!g_aOps[iOp].szName[1] || g_aOps[iOp].szName[1] == pszExpr[1])
1676 && (!g_aOps[iOp].szName[2] || g_aOps[iOp].szName[2] == pszExpr[2]))
1677 {
1678 /*
1679 * Check that we don't mistake it for some other operator which have more chars.
1680 */
1681 unsigned j;
1682 for (j = iOp + 1; j < RT_ELEMENTS(g_aOps); j++)
1683 if ( g_aOps[j].cchName > g_aOps[iOp].cchName
1684 && g_aOps[j].szName[0] == pszExpr[0]
1685 && (!g_aOps[j].szName[1] || g_aOps[j].szName[1] == pszExpr[1])
1686 && (!g_aOps[j].szName[2] || g_aOps[j].szName[2] == pszExpr[2]) )
1687 break;
1688 if (j < RT_ELEMENTS(g_aOps))
1689 continue; /* we'll catch it later. (for theoretical +,++,+++ cases.) */
1690 pOp = &g_aOps[iOp];
1691
1692 /*
1693 * Preferred type?
1694 */
1695 if (g_aOps[iOp].fBinary == fPreferBinary)
1696 break;
1697 }
1698 }
1699
1700 if (pOp)
1701 Log2(("dbgcOperatorLookup: pOp=%p %s\n", pOp, pOp->szName));
1702 NOREF(pDbgc); NOREF(chPrev);
1703 return pOp;
1704}
1705
Note: See TracBrowser for help on using the repository browser.

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette