ide/debugger: (#486) watches: don't show addresses where inappropriate
[sdk] / ide / src / debugger / debugTools.ec
1 import "ide"
2
3 #include <math.h>
4
5 static Map<String, uintptr> oneArgFns
6 { [
7    { "sqrt", (uintptr)sqrt },
8    { "log", (uintptr)log },
9    { "log10", (uintptr)log10 },
10    { "sin", (uintptr)sin },
11    { "cos", (uintptr)cos },
12    { "tan", (uintptr)tan },
13    { "asin", (uintptr)asin },
14    { "acos", (uintptr)acos },
15    { "atan", (uintptr)atan },
16    { "sinh", (uintptr)sinh },
17    { "cosh", (uintptr)cosh },
18    { "tanh", (uintptr)tanh },
19    { "asinh", (uintptr)asinh },
20    { "acosh", (uintptr)acosh },
21    { "atanh", (uintptr)atanh },
22    { "exp", (uintptr)exp },
23    { "floor", (uintptr)floor },
24    { "ceil", (uintptr)ceil },
25    { "fabs", (uintptr)sqrt }
26
27 ] };
28
29 static Map<String, uintptr> twoArgFns
30 { [
31    { "pow", (uintptr)pow },
32    { "atan2", (uintptr)atan2 },
33    { "fmod", (uintptr)fmod }
34 ] };
35
36 static void CarryExpressionError(Expression exp, Expression expError)
37 {
38    Expression temp { };
39
40    // This function assumes that expError is contained within exp,
41    // and therefore these types will be freed when freeing the old contents
42    // of the expression we're carying into.
43
44    if(expError.destType) expError.destType.refCount++;
45    if(expError.expType) expError.expType.refCount++;
46
47    *temp = *expError;
48
49    // -- Careful: this could be problematic as FreeExpContents will free the contents of expError
50    // Nulling things that may be freed now, but this is all overly messy/complex
51    switch(expError.type)
52    {
53       case functionCallErrorExp:
54          expError.call.exp = null;
55          expError.call.arguments = null;
56          break;
57       case symbolErrorExp:
58          expError.identifier = null;
59          break;
60       case memoryErrorExp:
61          expError.constant = null;
62          break;
63       case memberPropertyErrorExp:
64       case memberSymbolErrorExp:
65          expError.member.exp = null;
66          expError.member.member = null;
67          break;
68    }
69
70    /*
71    Identifier identifier = expError.identifier;
72    expError.identifier = null;
73    FreeExpContents(exp);
74    exp.identifier = identifier;
75    exp.type = expError.type;
76    */
77    if(exp.expType) FreeType(exp.expType);
78    if(exp.destType) FreeType(exp.destType);
79    FreeExpContents(exp);
80    *exp = *temp; //*expError;
81    delete temp;
82    // memset(expError, 0, sizeof(class Expression));
83 }
84
85 static char GetGdbFormatChar(Type type)
86 {
87 //          x : Regard the bits of the value as an integer, and print the integer in hexadecimal.
88 //          d : Print as integer in signed decimal.
89 //          u : Print as integer in unsigned decimal.
90 //          o : Print as integer in octal.
91 //          t : Print as integer in binary. The letter `t' stands for "two". (4)
92 //          a : Print as an address, both absolute in hexadecimal and as an offset from the nearest preceding symbol. You can use this format used to discover where (in what function) an unknown address is located:
93 //          c : Regard as an integer and print it as a character constant. This prints both the numerical value and its character representation. The character representation is replaced with the octal escape `\nnn' for characters outside the 7-bit ASCII range.
94 //          f : Regard the bits of the value as a floating point number and print using typical floating point syntax.
95    if(!type)
96       return 'x';
97
98    switch(type.kind)
99    {
100       case charType:
101          //return 'c';
102       case shortType:
103       case intType:
104       case longType:
105       case int64Type:
106          if(type.isSigned)
107             return 'd';
108          else
109             return 'u';
110       case floatType:
111          return 'f';
112       case doubleType:
113          return 'f';
114       case structType:
115       case unionType:
116       case functionType:
117       case arrayType:
118          // return 'u';
119          return 0;
120       case ellipsisType:
121       case enumType:
122       case methodType:
123       case vaListType:
124       // case TypeTypedObject, TypeAnyObject, TypeClassPointer:
125       case dummyType:
126          break;
127       case classType:
128       case pointerType:
129          return 'x';
130    }
131    return 'x';
132 }
133
134 /*static */bool ExpressionIsError(Expression exp)
135 {
136    return (exp.type == dereferenceErrorExp || exp.type == symbolErrorExp ||
137          exp.type == memberSymbolErrorExp || exp.type == memoryErrorExp || exp.type == unknownErrorExp ||
138          exp.type == noDebuggerErrorExp || exp.type == memberPropertyErrorExp || exp.type == functionCallErrorExp);
139 }
140
141 void DebugComputeExpression(Expression exp)
142 {
143 #ifdef _DEBUG
144    char expString[1024] = "";
145    //char temp[1024];
146    //if(inCompiler)
147       PrintExpression(exp, expString);
148    // printf("%s (exp.type = %s)\n", expString, exp.type.OnGetString(temp, null, null));
149 #endif
150    switch(exp.type)
151    {
152       case identifierExp:
153       {
154          Expression prev = exp.prev, next = exp.next;
155          char * evaluation = null;
156          ExpressionType evalError = dummyExp;
157          Expression expNew;
158          TypeKind kind = dummyType;
159          Type dataType = exp.expType;
160
161          char temp[1024];
162          uint64 address;
163          bool hasAddress;
164          bool isPointer = false;
165
166          if(dataType && dataType.kind == classType && dataType._class.registered)
167          {
168             Class _class = dataType._class.registered;
169             if(_class.type == bitClass || _class.type == unitClass || _class.type == enumClass)
170             {
171                if(!_class.dataType)
172                   _class.dataType = ProcessTypeString(_class.dataTypeString, false);
173                dataType = _class.dataType;
174             }
175             else if(_class.type == normalClass || _class.type == noHeadClass || _class.type == systemClass) // Added systemClass here for Instance
176             {
177                isPointer = true;
178             }
179          }
180          else if(dataType && dataType.kind == classType && !dataType._class.registered)
181             isPointer = true;
182          if(dataType)
183             kind = dataType.kind;
184          else
185             exp.type = symbolErrorExp;
186          temp[0] = '\0';
187          switch(kind)
188          {
189             case intPtrType: case intSizeType: case _BoolType:
190             case charType: case shortType: case intType: case int64Type: case longType: case floatType: case doubleType:
191             case enumType:
192             case arrayType:
193             case structType:
194             case pointerType:
195             case unionType:
196                sprintf(temp, "&%s", exp.identifier.string);
197                break;
198             case classType:
199                if(exp.byReference && dataType._class && dataType._class.registered && dataType._class.registered.type == structClass)
200                // if(!dataType._class || !dataType._class.registered || dataType._class.registered.type != structClass || exp.byReference)
201                   strcpy(temp, exp.identifier.string);
202                else
203                   sprintf(temp, "&%s", exp.identifier.string);
204                break;
205             case functionType:
206             case ellipsisType:
207             case methodType:
208             case vaListType:
209             // case TypeTypedObject, TypeAnyObject, TypeClassPointer:
210             case dummyType:
211                break;
212          }
213          if(temp[0])
214          {
215             evaluation = Debugger::EvaluateExpression(temp, &evalError);
216             if(evaluation)
217             {
218                address = _strtoui64(evaluation, null, 0);
219                //delete evaluation;
220                //evaluation = null;
221             }
222             else
223                address = 0;
224             hasAddress = true;
225          }
226          else
227             hasAddress = false;
228
229          if(evalError == dummyExp)
230          {
231             switch(kind)
232             {
233                case charType:
234                   delete evaluation;
235                   evaluation = Debugger::EvaluateExpression(exp.identifier.string, &evalError);
236                   if(evaluation)
237                   {
238                      //int c, len;
239                      char * temp;
240                      temp = strstr(evaluation, " '");
241                      //len = strlen(temp);
242                      if(temp)
243                         temp[0] = '\0';
244                      {/*
245                         for(c = 0; c < len; c++)
246                            temp[c] = ' ';
247                         eString_TrimRSpaces(evaluation, evaluation);
248                      */}
249                   }
250                   break;
251                case shortType:
252                case intType:
253                case longType:
254                case intPtrType:
255                case intSizeType:
256                case _BoolType:
257                case int64Type:
258                case floatType:
259                case doubleType:
260                case enumType:
261                case pointerType:
262                   delete evaluation;
263                   evaluation = Debugger::EvaluateExpression(exp.identifier.string, &evalError);
264                   if(evaluation)
265                   {
266                      if(kind == pointerType)
267                      {
268                         uint64 value;
269                         value = _strtoui64(evaluation, null, 0);
270                         delete evaluation;
271                         evaluation = PrintHexUInt64(value);
272                      }
273                   }
274                   break;
275                case classType:
276                   if(isPointer)
277                   {
278                      int size;
279                      char format;
280                      delete evaluation;
281                      //evaluation = Debugger::EvaluateExpression(exp.identifier.string, &evalError);
282                      size = ComputeTypeSize(exp.expType); //exp.expType.arrayType.size;
283                      format = GetGdbFormatChar(exp.expType);
284                      evaluation = Debugger::ReadMemory(address, size, format, &evalError);
285                      if(evaluation)
286                         StripQuotes(evaluation, evaluation);
287                   }
288                   break;
289                case structType:
290                case unionType:
291                case functionType:
292                   //evaluation = Debugger::EvaluateExpression(exp.identifier.string, &evalError);
293                   delete evaluation;
294                   break;
295                case arrayType:
296                {
297                   // for classType  --> if(_class.type == structClass) ?
298                   //char temp[1024];
299                   //sprintf(temp, "&%s", exp.identifier.string);
300                   //evaluation = Debugger::EvaluateExpression(temp, &evalError);
301                   break;
302                }
303                case ellipsisType:
304                case methodType:
305                case vaListType:
306                // case TypeTypedObject, TypeAnyObject, TypeClassPointer:
307                case dummyType:
308                   delete evaluation;
309                   evaluation = Debugger::EvaluateExpression(exp.identifier.string, &evalError);
310                   break;
311             }
312          }
313          switch(evalError)
314          {
315             case dummyExp:
316                if(evaluation)
317                {
318                   // Going back to parsing the expression string so as to catch inf/-inf/nan/-nan etc.
319                   expNew = ParseExpressionString(evaluation);
320                   //expNew = MkExpConstant(evaluation);
321                   //printf("Evaluation = %s\n", evaluation);
322                   delete evaluation;
323                   expNew.destType = exp.expType;
324
325                   // WHY EXACTLY MUST WE PROCESS THIS EXPRESSION TYPE AGAIN ? ADDED THIS FOR 0x00000000
326                   if(exp.expType && (exp.expType.kind == pointerType || exp.expType.kind == classType) && expNew.destType)
327                   {
328                      expNew.expType = expNew.destType;
329                      expNew.destType.refCount++;
330                   }
331                   else
332                      ProcessExpressionType(expNew);
333                   FreeType(exp.destType);
334                   FreeExpContents(exp);
335
336                   DebugComputeExpression(expNew);
337                   expNew.prev = prev;
338                   expNew.next = next;
339                   expNew.isConstant = true;
340                   expNew.address = address;
341                   expNew.hasAddress = hasAddress;
342                   *exp = *expNew;
343                   delete expNew;
344                }
345                else
346                {
347                   // Unhandled code path, evaluation is null
348                   FreeExpContents(exp);
349                   exp.type = unknownErrorExp;
350                }
351                break;
352             case symbolErrorExp:
353                // Keep the identifier
354                exp.type = evalError;
355                break;
356             default:
357                FreeExpContents(exp);
358                exp.type = evalError;
359                break;
360          }
361          break;
362       }
363       case instanceExp:
364       {
365          ComputeInstantiation(exp);
366          break;
367       }
368       /*
369       case constantExp:
370          break;
371       */
372       case opExp:
373       {
374          Expression expError = null;
375          Expression exp1, exp2 = null;
376          Operand op1 = { 0 }, op2 = { 0 };
377
378          /*
379          if(exp.op.op == '&' || exp.op.op == '*')
380          {
381             if(!exp.op.exp1 && exp.op.exp2)
382             {
383                if(exp.op.exp2.type == identifierExp)
384                {
385                   Expression prev = exp.prev, next = exp.next;
386                   char * evaluation = null;
387                   ExpressionType evalError = dummyExp;
388                   Expression expNew;
389                   char temp[1024];
390                   sprintf(temp, "%c%s", exp.op.op, exp.op.exp2.identifier.string);
391                   evaluation = Debugger::EvaluateExpression(temp, &evalError);
392                   if(evalError != dummyExp)
393                   {
394                      exp.type = evalError;
395                      exp.constant = CopyString("");
396                   }
397                   else if(evaluation)
398                   {
399                      expNew = ParseExpressionString(evaluation);
400                      delete evaluation;
401                      expNew.destType = exp.expType;
402                      FreeType(exp.destType);
403                      FreeExpContents(exp);
404                      ProcessExpressionType(expNew);
405                      DebugComputeExpression(expNew);
406                      expNew.prev = prev;
407                      expNew.next = next;
408                      expNew.isConstant = true;
409                      *exp = *expNew;
410                      delete expNew;
411                   }
412                   else
413                      exp.type = ExpUnknownError;
414                   break;
415                }
416                //else
417                {
418                   uint64 address;
419                   int size;
420                   char format;
421                   if(exp.op.op == '*')
422                   {
423                   DebugComputeExpression(exp.op.exp2);
424                   size = ComputeTypeSize(exp.op.exp2.expType);
425                   format = GetGdbFormatChar(exp.op.exp2.expType);
426                   GetInt(exp.op.exp2, &address);
427                   //sprintf(temp, "%c%s", exp.op.op, exp.op.exp2.constant);
428                   evaluation = Debug_ReadMemory(address, size, format, &evalError);
429                   }
430                   else
431                      evalError = ExpUnknownError;
432                }
433             }
434          }
435          */
436
437          // We don't care about operations with only exp2 (INC_OP, DEC_OP...)
438          if(exp.op.exp2)
439          {
440             Expression e = exp.op.exp2;
441
442             while((e.type == bracketsExp || e.type == extensionExpressionExp || e.type == extensionCompoundExp) && e.list)
443             {
444                if(e.type == bracketsExp || e.type == extensionExpressionExp || e.type == extensionCompoundExp)
445                {
446                   if(e.type == extensionCompoundExp)
447                      e = ((Statement)e.compound.compound.statements->last).expressions->last;
448                   else
449                      e = e.list->last;
450                }
451             }
452             if(exp.op.op == TokenType::sizeOf && e && e.expType)
453             {
454                if(e.type == stringExp && e.string)
455                {
456                   char * string = e.string;
457                   int len = strlen(string);
458                   char * tmp = new char[len-2+1];
459                   len = UnescapeString(tmp, string + 1, len - 2);
460                   delete tmp;
461                   FreeExpContents(exp);
462                   exp.type = constantExp;
463                   exp.constant = PrintUInt(len + 1);
464                }
465                else
466                {
467                   Type type = e.expType;
468                   type.refCount++;
469                   FreeExpContents(exp);
470                   exp.type = constantExp;
471                   exp.constant = PrintUInt(ComputeTypeSize(type));
472                   FreeType(type);
473                }
474                break;
475             }
476             else
477             {
478                DebugComputeExpression(exp.op.exp2);
479                if(ExpressionIsError(exp.op.exp2))
480                   expError = exp.op.exp2;
481             }
482          }
483          if(!expError)
484          {
485             if(exp.op.exp1)
486             {
487                DebugComputeExpression(exp.op.exp1);
488                if(ExpressionIsError(exp.op.exp1))
489                   expError = exp.op.exp1;
490                else
491                {
492                   if(exp.op.exp2)
493                   {
494                      if(ExpressionIsError(exp.op.exp2))
495                         expError = exp.op.exp2;
496                      else
497                      {
498                         exp1 = exp.op.exp1;
499                         exp2 = exp.op.exp2;
500                         op1 = GetOperand(exp1);
501                         if(op1.type) op1.type.refCount++;
502                         op2 = GetOperand(exp2);
503                         if(op2.type) op2.type.refCount++;
504                      }
505                   }
506                }
507             }
508             else if(exp.op.exp2)
509             {
510                if(ExpressionIsError(exp.op.exp2))
511                   expError = exp.op.exp2;
512                else
513                {
514                   exp1 = exp.op.exp2;
515                   if(exp.op.op == '&' || exp.op.op == '*')
516                   {
517                      Expression prev = exp1.prev, next = exp1.next;
518                      Expression expNew;
519                      ExpressionType evalError = dummyExp;
520                      char * evaluation = null;
521                      if(exp.op.op == '&')
522                      {
523                         if(exp1.hasAddress)
524                         {
525                            char * temp;
526                            //sprintf(temp, "%u", exp1.address);
527                            temp = PrintHexUInt64(exp1.address);
528                            expNew = ParseExpressionString(temp);
529                            delete temp;
530                            //expNew.address = exp1.address;
531                            expNew.expType = exp.expType;
532                            /*
533                            expNew.destType = exp.expType;
534                            expNew.destType.refCount++;
535                            */
536                            FreeType(exp.destType);
537                            FreeExpContents(exp);
538                            ProcessExpressionType(expNew);
539                            DebugComputeExpression(expNew);
540                            expNew.prev = prev;
541                            expNew.next = next;
542                            expNew.isConstant = true;
543                            *exp = *expNew;
544                            delete expNew;
545                         }
546                         else
547                            exp1.address = 0;
548                      }
549                      else if(exp.op.op == '*')
550                      {
551                         // TODO: Common pathway for * and [ ]
552                         if(!exp.expType)
553                         {
554                            delete evaluation;
555                            FreeExpContents(exp1);
556                            exp1.type = dereferenceErrorExp;
557                            expError = exp1;
558                         }
559                         else
560                         {
561                            uint64 address = 0;
562                            int size;
563                            char format;
564                            Expression e = exp1;
565                            uint offset = 0;
566                            bool gotAddress = false;
567
568                            while(((e.type == bracketsExp || e.type == extensionExpressionExp || e.type == extensionCompoundExp) && e.list) || e.type == castExp)
569                            {
570                               if(e.type == bracketsExp || e.type == extensionExpressionExp || e.type == extensionCompoundExp)
571                               {
572                                  if(e.type == extensionCompoundExp)
573                                     e = ((Statement)e.compound.compound.statements->last).expressions->last;
574                                  else
575                                     e = e.list->last;
576                               }
577                               else if(e.type == castExp)
578                                  e = e.cast.exp;
579                            }
580
581                            if(e.expType.kind == structType)
582                            {
583                               address = exp1.address;
584                               gotAddress = true;
585                            }
586                            else
587                               gotAddress = GetUInt64(e, &address);
588                            size = ComputeTypeSize(exp.expType); //exp.expType.arrayType.size;
589                            if(exp.expType && exp.expType.type && exp.expType.kind == arrayType)
590                               // For multilevels arrays
591                               format = 'x';
592                            else
593                               format = GetGdbFormatChar(exp.expType);
594                            while(e.type == opExp && e.op.op == '+' && e.op.exp1 && e.op.exp2)
595                            {
596                               Expression e1 = e.op.exp1, e2 = e.op.exp2;
597                               while(((e1.type == bracketsExp || e1.type == extensionExpressionExp || e1.type == extensionCompoundExp) && e1.list) || e1.type == castExp)
598                               {
599                                  if(e1.type == bracketsExp || e1.type == extensionExpressionExp || e1.type == extensionCompoundExp)
600                                  {
601                                     if(e1.type == extensionCompoundExp)
602                                        e1 = ((Statement)e1.compound.compound.statements->last).expressions->last;
603                                     else
604                                        e1 = e1.list->last;
605                                  }
606                                  else if(e1.type == castExp)
607                                     e1 = e1.cast.exp;
608                               }
609                               while(((e2.type == bracketsExp || e2.type == extensionExpressionExp || e2.type == extensionCompoundExp) && e2.list) || e2.type == castExp)
610                               {
611                                  if(e2.type == bracketsExp || e2.type == extensionExpressionExp || e2.type == extensionCompoundExp)
612                                  {
613                                     if(e2.type == extensionCompoundExp)
614                                        e2 = ((Statement)e2.compound.compound.statements->last).expressions->last;
615                                     else
616                                        e2 = e2.list->last;
617                                  }
618                                  else if(e2.type == castExp)
619                                     e2 = e2.cast.exp;
620                               }
621
622                               if((e1.type == stringExp || e1.type == opExp) && e.op.exp2.isConstant && e.op.exp2.expType && e.op.exp2.expType.kind == intType)
623                               {
624                                  offset += strtol(e.op.exp2.constant, null, 0);
625                                  e = e1;
626                               }
627                               else if((e2.type == stringExp || e2.type == opExp) && e.op.exp1.isConstant && e.op.exp1.expType && e.op.exp1.expType.kind == intType)
628                               {
629                                  offset += strtol(e.op.exp1.constant, null, 0);
630                                  e = e2;
631                               }
632                               else
633                                   break;
634                            }
635
636                            if(e.type == stringExp)
637                            {
638                               char * tmp = null;
639                               String string = e.string;
640                               bool valid = false;
641                               Type expType = exp1.expType.type;
642                               if(expType) expType.refCount++;
643
644                               if(string)
645                               {
646                                  int len = string ? strlen(string) : 0;
647                                  tmp = new char[len-2+1];
648                                  len = UnescapeString(tmp, string + 1, len - 2);
649                                  if(len >= 0 && offset * size + size-1 <= len)
650                                     valid = true;
651                               }
652
653                               FreeExpContents(exp);
654                               if(!valid)
655                                  exp.type = dereferenceErrorExp;
656                               else if(expType)
657                               {
658                                  exp.type = constantExp;
659                                  exp.isConstant = true;
660                                  switch(expType.kind)
661                                  {
662                                     case charType:   exp.constant = expType.isSigned ? PrintChar(((char *)tmp)[offset]) : PrintUChar(((byte *)tmp)[offset]); break;
663                                     case shortType:  exp.constant = expType.isSigned ? PrintShort(((short *)tmp)[offset]) : PrintUShort(((uint16 *)tmp)[offset]); break;
664                                     case intType:    exp.constant = expType.isSigned ? PrintInt(((int *)tmp)[offset]) : PrintUInt(((uint *)tmp)[offset]); break;
665                                     case int64Type:  exp.constant = expType.isSigned ? PrintInt64(((int64 *)tmp)[offset]) : PrintUInt64(((uint64 *)tmp)[offset]); break;
666                                     case floatType:  exp.constant = PrintFloat(((float *)tmp)[offset]); break;
667                                     case doubleType: exp.constant = PrintDouble(((double *)tmp)[offset]); break;
668                                     default:
669                                        exp.type = unknownErrorExp;
670                                  }
671                               }
672                               else
673                                  exp.type = unknownErrorExp;
674                               FreeType(expType);
675                               delete tmp;
676                            }
677                            else if(gotAddress && exp.expType.kind == arrayType)
678                            {
679                               FreeExpContents(exp);
680                               exp.type = constantExp;
681                               exp.isConstant = true;
682                               exp.constant = PrintHexUInt64(address);
683                               exp.address = address;
684                               exp.hasAddress = true;
685                            }
686                            else if(gotAddress && format)
687                            {
688                               evaluation = Debugger::ReadMemory(address, size, format, &evalError);
689                               switch(evalError)
690                               {
691                                  case dummyExp:
692                                     if(evaluation)
693                                     {
694                                        expNew = ParseExpressionString(evaluation);
695                                        expNew.address = address;
696                                        expNew.hasAddress = true;
697                                        delete evaluation;
698                                        expNew.destType = exp.expType;
699                                        FreeType(exp.destType);
700                                        FreeExpContents(exp);
701                                        ProcessExpressionType(expNew);
702                                        DebugComputeExpression(expNew);
703                                        expNew.prev = prev;
704                                        expNew.next = next;
705                                        expNew.isConstant = true;
706                                        *exp = *expNew;
707                                        delete expNew;
708                                     }
709                                     else
710                                     {
711                                        // Unhandled code path, evaluation is null
712                                        FreeExpContents(exp);
713                                        exp.type = unknownErrorExp;
714                                     }
715                                     break;
716                                  case memoryErrorExp:
717                                     delete evaluation;
718                                     FreeExpContents(exp1);
719                                     exp1.type = evalError;
720                                     exp1.constant = PrintHexUInt64(address);
721                                     expError = exp1;
722                                     break;
723                                  default:
724                                     delete evaluation;
725                                     FreeExpContents(exp1);
726                                     exp1.type = evalError;
727                                     expError = exp1;
728                                     break;
729                               }
730                            }
731                            else
732                            {
733                               FreeExpContents(exp1);
734                               exp1.type = unknownErrorExp;  // Not supported yet, generate error to fallback to GDB printout
735                               expError = exp1;
736                            }
737                         }
738                      }
739                   }
740                   else
741                      op1 = GetOperand(exp1);
742                   if(op1.type) op1.type.refCount++;
743                }
744             }
745          }
746          if(expError)
747             CarryExpressionError(exp, expError);
748          else if(exp.type == opExp)
749          {
750             if(exp1 && exp2 && exp1.expType && exp2.expType &&
751                ((exp1.expType.kind == pointerType || exp1.expType.kind == arrayType) ||
752                 (exp2.expType.kind == pointerType || exp2.expType.kind == arrayType)))
753             {
754                bool valid = false;
755                // TODO: Support 1 + pointer
756                if((exp.op.op == '+' || exp.op.op == '-') && exp2.expType && op2.type && op2.type.kind == intType)
757                {
758                   Expression e = exp1;
759                   while(((e.type == bracketsExp || e.type == extensionExpressionExp || e.type == extensionCompoundExp) && e.list) || e.type == castExp)
760                   {
761                      if(e.type == bracketsExp || e.type == extensionExpressionExp || e.type == extensionCompoundExp)
762                      {
763                         if(e.type == extensionCompoundExp)
764                            e = ((Statement)e.compound.compound.statements->last).expressions->last;
765                         else
766                            e = e.list->last;
767                      }
768                      else if(e.type == castExp)
769                         e = e.cast.exp;
770                   }
771
772                   if(e.type == stringExp)
773                   {
774                      uint64 offset = (exp.op.op == '+') ? op2.i64 : -op2.i64;
775                      String newString = null;
776                      if(e.string)
777                      {
778                         int len = strlen(e.string) - 2;
779                         char * tmp = OffsetEscapedString(e.string + 1, len, (int)offset);
780                         if(tmp)
781                         {
782                            len -= tmp - (e.string + 1);
783                            newString = new char[2 + len];
784                            newString[0] = '\"';
785                            memcpy(newString + 1, tmp, len);
786                            newString[1 + len] = '\"';
787                            newString[1 + len + 1] = 0;
788                         }
789                      }
790                      valid = true;
791                      FreeExpContents(exp);
792                      if(newString)
793                      {
794                         exp.type = stringExp;
795                         exp.string = newString;
796                      }
797                      else
798                         exp.type = dereferenceErrorExp;
799                   }
800                   else if(op1.type)
801                   {
802                      // TODO: Do pointer operations
803                      if(exp1.expType && exp1.expType.type)
804                      {
805                         uint size = ComputeTypeSize(exp1.expType.type);
806                         if(size)
807                         {
808                            valid = true;
809                            op1.ui64 /= exp1.expType.type.size;
810                            CallOperator(exp, exp1, exp2, op1, op2);
811                            if(exp.type == constantExp)
812                            {
813                               exp.address = _strtoui64(exp.constant, null, 0);
814                               exp.address *= size;
815                               if(op1.type.kind == arrayType)
816                                  exp.hasAddress = true;
817                            }
818                         }
819                      }
820                   }
821                }
822                if(!valid)
823                {
824                   FreeExpContents(exp);
825                   exp.type = unknownErrorExp;   // We should have an invalid operands error
826                }
827             }
828             else
829             {
830                if(!exp2 && exp1 && exp1.type == constantExp && exp1.constant && !strcmp(exp1.constant, "nan") && exp.op.op == '-')
831                {
832                   FreeExpContents(exp);
833                   exp.constant = CopyString("-nan");
834                   exp.type = constantExp;
835                }
836                else
837                   CallOperator(exp, exp1, exp2, op1, op2);
838             }
839             FreeType(op1.type);
840             FreeType(op2.type);
841             if(exp.type == constantExp)
842                exp.isConstant = true;
843          }
844          break;
845       }
846       case bracketsExp:
847       {
848          Expression e, n;
849          //for(
850          //   e = (*exp.list).first, n = e ? e.next : null;
851          //   e;
852          //   e = n, n = n?(n.next) : null)
853
854          for(e = exp.list->first; e; e = n)
855          {
856             n = e.next;
857             if(!n)
858             {
859                OldList * list = exp.list;
860                DebugComputeExpression(e);
861                //if(ExpressionIsError(e)) //.type == ExpSymbolError
862                //   CarryExpressionError(exp, e);
863                //FreeExpContents(exp);
864                FreeType(exp.expType);
865                FreeType(exp.destType);
866                *exp = *e;
867                delete e;
868                delete list;
869             }
870             else
871             {
872                FreeExpression(e);
873             }
874          }
875          break;
876       }
877       case indexExp:
878       {
879          int size;
880          char format;
881          Expression e;
882          exp.isConstant = true;
883
884          DebugComputeExpression(exp.index.exp);
885          if(ExpressionIsError(exp.index.exp)) //.type == ExpSymbolError
886             CarryExpressionError(exp, exp.index.exp);
887          else
888          {
889             Expression prev = exp.prev, next = exp.next;
890             char * evaluation = null;
891             ExpressionType evalError = dummyExp;
892
893             if(!exp.index.exp.isConstant)
894                exp.isConstant = false;
895
896             // int r[0]
897             // 4 == size = ComputeTypeSize(exp.expType);
898             // 0 == size = ComputeTypeSize(exp.expType.arrayType);
899             // 4 == size = ComputeTypeSize(exp.index.exp.expType);
900             // 0 == size = ComputeTypeSize(exp.index.exp.expType.arrayType);
901
902             size = ComputeTypeSize(exp.expType);
903             if(exp.expType && exp.expType.type && exp.expType.kind == arrayType)
904                // For multilevels arrays
905                format = 'x';
906             else
907                format = GetGdbFormatChar(exp.expType);
908
909             for(e = exp.index.index->first; e; e = e.next)
910             {
911                DebugComputeExpression(e);
912                if(ExpressionIsError(e)) //.type == ExpSymbolError
913                {
914                   CarryExpressionError(exp, e);
915                   break;
916                }
917                if(!e.next)
918                {
919                   // Check if this type is int
920                }
921                if(!e.isConstant)
922                   exp.isConstant = false;
923             }
924             if(!ExpressionIsError(exp))
925             {
926                // Is this necessary here? pass15 had done this already...
927                if(exp.expType) FreeType(exp.expType);
928                exp.expType = Dereference(exp.index.exp.expType);
929
930                if(!exp.expType)
931                {
932                   delete evaluation;
933                   FreeExpContents(exp);
934                   exp.type = dereferenceErrorExp;
935                }
936                else if(exp.index.index && exp.index.index->last && ((Expression)exp.index.index->last) && ((Expression)exp.index.index->last).expType)
937                {
938                   Type type = ((Expression)exp.index.index->last).expType;
939                   if(type.kind == intType || type.kind == charType || type.kind == shortType || type.kind == int64Type || type.kind == intPtrType ||
940                      type.kind == intSizeType || type.kind == longType || type.kind == _BoolType || type.kind == enumType ||
941                         (type.kind == classType && type._class && type._class.registered &&
942                            type._class.registered.type == enumClass))
943                   {
944                      bool gotAddress = false;
945                      uint64 address = 0, offset = 0;
946                      Expression expNew, last = (Expression)exp.index.index->last;
947                      Expression e = exp.index.exp;
948
949                      while(((e.type == bracketsExp || e.type == extensionExpressionExp || e.type == extensionCompoundExp) && e.list) || e.type == castExp)
950                      {
951                         if(e.type == bracketsExp || e.type == extensionExpressionExp || e.type == extensionCompoundExp)
952                         {
953                            if(e.type == extensionCompoundExp)
954                               e = ((Statement)e.compound.compound.statements->last).expressions->last;
955                            else
956                               e = e.list->last;
957                         }
958                         else if(e.type == castExp)
959                            e = e.cast.exp;
960                      }
961
962                      //GetUInt(exp.index.exp, &address);
963
964                      GetUInt64(last, &offset);
965
966                      // TOFIX: Check if it has address: TESTING
967                      if(exp.index.exp.hasAddress && exp.index.exp.expType.kind == arrayType)
968                      {
969                         address = exp.index.exp.address;
970                         gotAddress = true;
971                      }
972                      else if(exp.index.exp.type == constantExp)
973                         gotAddress = GetUInt64(exp.index.exp, &address);
974
975                      while(e.type == opExp && e.op.op == '+' && e.op.exp1 && e.op.exp2)
976                      {
977                         Expression e1 = e.op.exp1, e2 = e.op.exp2;
978                         while(((e1.type == bracketsExp || e1.type == extensionExpressionExp || e1.type == extensionCompoundExp) && e1.list) || e1.type == castExp)
979                         {
980                            if(e1.type == bracketsExp || e1.type == extensionExpressionExp || e1.type == extensionCompoundExp)
981                            {
982                               if(e1.type == extensionCompoundExp)
983                                  e1 = ((Statement)e1.compound.compound.statements->last).expressions->last;
984                               else
985                                  e1 = e1.list->last;
986                            }
987                            else if(e1.type == castExp)
988                               e1 = e1.cast.exp;
989                         }
990                         while(((e2.type == bracketsExp || e2.type == extensionExpressionExp || e2.type == extensionCompoundExp) && e2.list) || e2.type == castExp)
991                         {
992                            if(e2.type == bracketsExp || e2.type == extensionExpressionExp || e2.type == extensionCompoundExp)
993                            {
994                               if(e2.type == extensionCompoundExp)
995                                  e2 = ((Statement)e2.compound.compound.statements->last).expressions->last;
996                               else
997                                  e2 = e2.list->last;
998                            }
999                            else if(e2.type == castExp)
1000                               e2 = e2.cast.exp;
1001                         }
1002
1003                         if((e1.type == stringExp || e1.type == opExp) && e.op.exp2.isConstant && e.op.exp2.expType && e.op.exp2.expType.kind == intType)
1004                         {
1005                            offset += strtol(e.op.exp2.constant, null, 0);
1006                            e = e1;
1007                         }
1008                         else if((e2.type == stringExp || e2.type == opExp) && e.op.exp1.isConstant && e.op.exp1.expType && e.op.exp1.expType.kind == intType)
1009                         {
1010                            offset += strtol(e.op.exp1.constant, null, 0);
1011                            e = e2;
1012                         }
1013                         else
1014                             break;
1015                      }
1016
1017                      //size = ComputeTypeSize(exp.expType.arrayType); //exp.expType.arrayType.size;
1018                      address += offset * size;
1019
1020                      if(e.type == stringExp)
1021                      {
1022                         char * tmp = null;
1023                         String string = e.string;
1024                         bool valid = false;
1025                         Type expType = exp.index.exp.expType.type;
1026                         if(expType) expType.refCount++;
1027
1028                         if(string)
1029                         {
1030                            int len = string ? strlen(string) : 0;
1031                            tmp = new char[len-2+1];
1032                            len = UnescapeString(tmp, string + 1, len - 2);
1033                            if(len >= 0 && offset * size + size-1 <= len)
1034                               valid = true;
1035                         }
1036
1037                         FreeExpContents(exp);
1038                         if(!valid)
1039                            exp.type = dereferenceErrorExp;
1040                         else if(expType)
1041                         {
1042                            exp.type = constantExp;
1043                            exp.isConstant = true;
1044                            switch(expType.kind)
1045                            {
1046                               case charType:   exp.constant = expType.isSigned ? PrintChar(((char *)tmp)[offset]) : PrintUChar(((byte *)tmp)[offset]); break;
1047                               case shortType:  exp.constant = expType.isSigned ? PrintShort(((short *)tmp)[offset]) : PrintUShort(((uint16 *)tmp)[offset]); break;
1048                               case intType:    exp.constant = expType.isSigned ? PrintInt(((int *)tmp)[offset]) : PrintUInt(((uint *)tmp)[offset]); break;
1049                               case int64Type:  exp.constant = expType.isSigned ? PrintInt64(((int64 *)tmp)[offset]) : PrintUInt64(((uint64 *)tmp)[offset]); break;
1050                               case floatType:  exp.constant = PrintFloat(((float *)tmp)[offset]); break;
1051                               case doubleType: exp.constant = PrintDouble(((double *)tmp)[offset]); break;
1052                               default:
1053                                  exp.type = unknownErrorExp;
1054                            }
1055                         }
1056                         else
1057                            exp.type = unknownErrorExp;
1058                         FreeType(expType);
1059                         delete tmp;
1060                      }
1061                      else if(gotAddress && exp.expType.kind == arrayType)
1062                      {
1063                         FreeExpContents(exp);
1064                         exp.type = constantExp;
1065                         exp.isConstant = true;
1066                         exp.constant = PrintHexUInt64(address);
1067                         exp.address = address;
1068                         exp.hasAddress = true;
1069                      }
1070                      else if(gotAddress)
1071                      {
1072                         evaluation = Debugger::ReadMemory(address, size, format, &evalError);
1073                         switch(evalError)
1074                         {
1075                            case dummyExp:
1076                               if(evaluation)
1077                               {
1078                                  expNew = ParseExpressionString(evaluation);
1079                                  delete evaluation;
1080                                  expNew.destType = exp.expType;
1081                                  FreeType(exp.destType);
1082                                  FreeExpContents(exp);
1083                                  ProcessExpressionType(expNew);
1084                                  DebugComputeExpression(expNew);
1085
1086                                  // TOFIX: Only for Array Types
1087                                  expNew.address = address;
1088
1089                                  expNew.hasAddress = true;
1090                                  expNew.prev = prev;
1091                                  expNew.next = next;
1092                                  expNew.isConstant = true;
1093                                  *exp = *expNew;
1094                                  delete expNew;
1095                               }
1096                               else
1097                               {
1098                                  // Unhandled code path, evaluation is null
1099                                  FreeExpContents(exp);
1100                                  exp.type = unknownErrorExp;
1101                               }
1102                               break;
1103                            case memoryErrorExp:
1104                               delete evaluation;
1105                               FreeExpContents(exp);
1106                               exp.type = evalError;
1107                               exp.constant = PrintHexUInt64(address);
1108                               break;
1109                            default:
1110                               delete evaluation;
1111                               FreeExpContents(exp);
1112                               exp.type = evalError;
1113                               break;
1114                         }
1115                      }
1116                      else
1117                      {
1118                         FreeExpContents(exp);
1119                         exp.type = unknownErrorExp;
1120                      }
1121                   }
1122                }
1123             }
1124          }
1125          break;
1126       }
1127       case callExp:
1128       {
1129          Expression callExp = exp.call.exp;
1130          Identifier id = (callExp && callExp.type == identifierExp) ? callExp.identifier : null;
1131          bool resolved = false;
1132          if(id && id.string)
1133          {
1134             if(!strcmp(id.string, "nan") || !strcmp(id.string, "inf"))
1135             {
1136                String s = id.string;
1137                id.string = null;
1138                FreeExpContents(exp);
1139                exp.type = constantExp;
1140                exp.constant = s;
1141                resolved = true;
1142             }
1143             else if(exp.call.arguments)
1144             {
1145                if(exp.call.arguments->count == 1)
1146                {
1147                   double (* fn1)(double) = (void *)oneArgFns[id.string];
1148                   if(fn1)
1149                   {
1150                      Expression arg = exp.call.arguments->first;
1151                      DebugComputeExpression(arg);
1152                      if(ExpressionIsError(arg))
1153                         CarryExpressionError(exp, arg);
1154                      else if(arg.isConstant && arg.type == constantExp)
1155                      {
1156                         double v;
1157                         if(GetDouble(arg, &v))
1158                         {
1159                            FreeExpContents(exp);
1160                            exp.type = constantExp;
1161                            v = fn1(v);
1162                            exp.constant = PrintDouble(v);
1163                            exp.isConstant = true;
1164                            resolved = true;
1165                         }
1166                      }
1167                   }
1168                }
1169                else if(exp.call.arguments->count == 2)
1170                {
1171                   double (* fn2)(double, double) = (void *)twoArgFns[id.string];
1172                   if(fn2)
1173                   {
1174                      Expression arg1 = exp.call.arguments->first;
1175                      Expression arg2 = exp.call.arguments->last;
1176                      DebugComputeExpression(arg1);
1177                      DebugComputeExpression(arg2);
1178                      if(ExpressionIsError(arg1))
1179                         CarryExpressionError(exp, arg1);
1180                      else if(ExpressionIsError(arg2))
1181                         CarryExpressionError(exp, arg2);
1182                      else if(arg1.isConstant && arg1.type == constantExp && arg2.isConstant && arg2.type == constantExp)
1183                      {
1184                         double v1, v2;
1185                         if(GetDouble(arg1, &v1) && GetDouble(arg2, &v2))
1186                         {
1187                            FreeExpContents(exp);
1188                            exp.type = constantExp;
1189                            v1 = fn2(v1, v2);
1190                            exp.constant = PrintDouble(v1);
1191                            exp.isConstant = true;
1192                            resolved = true;
1193                         }
1194                      }
1195                   }
1196                }
1197             }
1198          }
1199          if(!resolved)
1200             exp.type = functionCallErrorExp;
1201          break;
1202       }
1203       case memberExp:
1204       {
1205          Expression memberExp = exp.member.exp;
1206          Identifier memberID = exp.member.member;
1207          //Class _class;
1208          Property prop = null;
1209          DataMember member = null;
1210          Class convertTo = null;
1211          uint offset = 0;  // THIS WASN'T INITIALIZED... IS IT ALWAYS SET?
1212
1213          Type type; // = memberExp.expType;
1214          DebugComputeExpression(memberExp);
1215          type = memberExp.expType;
1216          if(ExpressionIsError(memberExp))
1217             CarryExpressionError(exp, memberExp);
1218          else if(type)
1219          {
1220             // _class = (memberID && memberID.classSym) ? memberID.classSym.registered : ((type.kind == classType && type._class) ? type._class.registered : null);
1221             Class _class = (exp.member.member && exp.member.member.classSym) ? exp.member.member.classSym.registered : (((type.kind == classType || type.kind == subClassType) && type._class) ? type._class.registered : null);
1222             if(!_class)
1223             {
1224                char string[256] = "";
1225                Symbol classSym;
1226                PrintTypeNoConst(type, string, false, true);
1227                classSym = FindClass(string);
1228                _class = classSym ? classSym.registered : null;
1229             }
1230
1231             if(memberID && _class)
1232             {
1233                /*
1234                prop = eClass_FindProperty(_class, memberID.string);
1235                if(!prop)
1236                   member = eClass_FindDataMember(_class, memberID.string);
1237                */
1238                // member = eClass_FindDataMember(_class, memberID.string);
1239                member = eClass_FindDataMemberAndOffset(_class, memberID.string, &offset, _class.module.application, null, null);
1240                if(!member)
1241                   prop = eClass_FindProperty(_class, memberID.string, _class.module.application);
1242             }
1243             if(!prop && !member && _class && memberID)
1244             {
1245                Symbol classSym = FindClass(memberID.string);
1246                convertTo = _class;
1247                _class = classSym ? classSym.registered : null;
1248                if(_class)
1249                   prop = eClass_FindProperty(_class, convertTo.name, _class.module.application);
1250             }
1251
1252             //DebugComputeExpression(memberExp);
1253             if(ExpressionIsError(memberExp))
1254                CarryExpressionError(exp, memberExp);
1255             else
1256             {
1257                if(exp.member.memberType == methodMember)
1258                {
1259                   FreeExpContents(exp);
1260                   exp.type = unknownErrorExp;
1261                }
1262                else if(prop)
1263                {
1264                   bool supported = false;
1265                   if(prop.compiled)
1266                   {
1267                      Type type = prop.dataType;
1268                      // TODO: Assuming same base type for units...
1269                      if(_class.type == unitClass)
1270                      {
1271                         if(type.kind == classType)
1272                         {
1273                            Class _class = type._class.registered;
1274                            if(_class.type == unitClass)
1275                            {
1276                               if(!_class.dataType)
1277                                  _class.dataType = ProcessTypeString(_class.dataTypeString, false);
1278                               type = _class.dataType;
1279                            }
1280                         }
1281                         switch(type.kind)
1282                         {
1283                            case floatType:
1284                            {
1285                               float value;
1286                               float (*Get)(float) = (void *)prop.Get;
1287                               GetFloat(memberExp, &value);
1288                               exp.constant = PrintFloat(Get ? Get(value) : value);
1289                               exp.type = constantExp;
1290                               supported = true;
1291                               break;
1292                            }
1293                            case doubleType:
1294                            {
1295                               double value;
1296                               double (*Get)(double);
1297                               GetDouble(memberExp, &value);
1298
1299                               if(convertTo)
1300                                  Get = (void *)prop.Set;
1301                               else
1302                                  Get = (void *)prop.Get;
1303                               exp.constant = PrintDouble(Get ? Get(value) : value);
1304                               exp.type = constantExp;
1305                               supported = true;
1306                               break;
1307                            }
1308                         }
1309                      }
1310                      else
1311                      {
1312                         if(convertTo)
1313                         {
1314                            Expression value = memberExp;
1315                            Type type = prop.dataType;
1316                            if(_class.type == structClass)
1317                            {
1318                               switch(type.kind)
1319                               {
1320                                  case classType:
1321                                  {
1322                                     Class propertyClass = type._class.registered;
1323                                     if(propertyClass.type == structClass && value.type == instanceExp)
1324                                     {
1325                                        void (*Set)(void *, void *) = (void *)prop.Set;
1326                                        exp.instance = Instantiation
1327                                        {
1328                                           data = new0 byte[_class.structSize];
1329                                           _class = MkSpecifierName/*MkClassName*/(_class.name);
1330                                           loc = exp.loc;
1331                                           exp.type = instanceExp;
1332                                        };
1333                                        Set(exp.instance.data, value.instance.data);
1334                                        PopulateInstance(exp.instance);
1335                                        supported = true;
1336                                     }
1337                                     break;
1338                                  }
1339                                  case intType:
1340                                  {
1341                                     int intValue;
1342                                     void (*Set)(void *, int) = (void *)prop.Set;
1343
1344                                     exp.instance = Instantiation
1345                                     {
1346                                        data = new0 byte[_class.structSize];
1347                                        _class = MkSpecifierName/*MkClassName*/(_class.name);
1348                                        loc = exp.loc;
1349                                     };
1350                                     exp.type = instanceExp;
1351
1352                                     GetInt(value, &intValue);
1353
1354                                     Set(exp.instance.data, intValue);
1355                                     PopulateInstance(exp.instance);
1356                                     supported = true;
1357                                     break;
1358                                  }
1359                                  case int64Type:
1360                                  {
1361                                     int64 intValue;
1362                                     void (*Set)(void *, int64) = (void *)prop.Set;
1363
1364                                     exp.instance = Instantiation
1365                                     {
1366                                        data = new0 byte[_class.structSize];
1367                                        _class = MkSpecifierName/*MkClassName*/(_class.name);
1368                                        loc = exp.loc;
1369                                     };
1370                                     exp.type = instanceExp;
1371
1372                                     GetInt64(value, &intValue);
1373
1374                                     Set(exp.instance.data, intValue);
1375                                     PopulateInstance(exp.instance);
1376                                     supported = true;
1377                                     break;
1378                                  }
1379                                  case doubleType:
1380                                  {
1381                                     double doubleValue;
1382                                     void (*Set)(void *, double) = (void *)prop.Set;
1383
1384                                     exp.instance = Instantiation
1385                                     {
1386                                        data = new0 byte[_class.structSize];
1387                                        _class = MkSpecifierName/*MkClassName*/(_class.name);
1388                                        loc = exp.loc;
1389                                     };
1390                                     exp.type = instanceExp;
1391
1392                                     GetDouble(value, &doubleValue);
1393
1394                                     Set(exp.instance.data, doubleValue);
1395                                     PopulateInstance(exp.instance);
1396                                     supported = true;
1397                                     break;
1398                                  }
1399                               }
1400                            }
1401                            else if(_class.type == bitClass)
1402                            {
1403                               switch(type.kind)
1404                               {
1405                                  case classType:
1406                                  {
1407                                     Class propertyClass = type._class.registered;
1408                                     if(propertyClass.type == structClass && value.instance.data)
1409                                     {
1410                                        unsigned int (*Set)(void *) = (void *)prop.Set;
1411                                        unsigned int bits = Set(value.instance.data);
1412                                        exp.constant = PrintHexUInt(bits);
1413                                        exp.type = constantExp;
1414                                        supported = true;
1415                                        break;
1416                                     }
1417                                     else if(_class.type == bitClass)
1418                                     {
1419                                        unsigned int value;
1420                                        unsigned int (*Set)(unsigned int) = (void *)prop.Set;
1421                                        unsigned int bits;
1422
1423                                        GetUInt(memberExp, &value);
1424                                        bits = Set(value);
1425                                        exp.constant = PrintHexUInt(bits);
1426                                        exp.type = constantExp;
1427                                        supported = true;
1428                                     }
1429                                  }
1430                               }
1431                            }
1432                         }
1433                         else
1434                         {
1435                            if(_class.type == bitClass)
1436                            {
1437                               uint value;
1438                               GetUInt(memberExp, &value);
1439
1440                               switch(type.kind)
1441                               {
1442                                  case classType:
1443                                  {
1444                                     Class _class = type._class.registered;
1445                                     if(_class.type == structClass)
1446                                     {
1447                                        void (*Get)(unsigned int, void *) = (void *)prop.Get;
1448
1449                                        exp.instance = Instantiation
1450                                        {
1451                                           data = new0 byte[_class.structSize];
1452                                           _class = MkSpecifierName/*MkClassName*/(_class.name);
1453                                           loc = exp.loc;
1454                                        };
1455                                        //exp.instance.fullSet = true;
1456                                        exp.type = instanceExp;
1457                                        Get(value, exp.instance.data);
1458                                        PopulateInstance(exp.instance);
1459                                        supported = true;
1460                                     }
1461                                     else if(_class.type == bitClass)
1462                                     {
1463                                        unsigned int (*Get)(unsigned int) = (void *)prop.Get;
1464                                        uint64 bits = Get(value);
1465                                        exp.constant = PrintHexUInt64(bits);
1466                                        exp.type = constantExp;
1467                                        supported = true;
1468                                     }
1469                                     break;
1470                                  }
1471                               }
1472                            }
1473                            else if(_class.type == structClass)
1474                            {
1475                               char * value = (memberExp.type == instanceExp ) ? memberExp.instance.data : null;
1476                               switch(type.kind)
1477                               {
1478                                  case classType:
1479                                  {
1480                                     Class _class = type._class.registered;
1481                                     if(_class.type == structClass && value)
1482                                     {
1483                                        void (*Get)(void *, void *) = (void *)prop.Get;
1484
1485                                        exp.instance = Instantiation
1486                                        {
1487                                           data = new0 byte[_class.structSize];
1488                                           _class = MkSpecifierName/*MkClassName*/(_class.name);
1489                                           loc = exp.loc;
1490                                        };
1491                                        //exp.instance.fullSet = true;
1492                                        exp.type = instanceExp;
1493                                        Get(value, exp.instance.data);
1494                                        PopulateInstance(exp.instance);
1495                                        supported = true;
1496                                     }
1497                                     break;
1498                                  }
1499                               }
1500                            }
1501                            /*else
1502                            {
1503                               char * value = memberExp.instance.data;
1504                               switch(type.kind)
1505                               {
1506                                  case classType:
1507                                  {
1508                                     Class _class = type._class.registered;
1509                                     if(_class.type == normalClass)
1510                                     {
1511                                        void *(*Get)(void *) = (void *)prop.Get;
1512
1513                                        exp.instance = Instantiation
1514                                        {
1515                                           data = Get(value, exp.instance.data);     ?????
1516                                           _class = MkSpecifierName(_class.name); //MkClassName(_class.name);
1517                                           loc = exp.loc;
1518                                        };
1519                                        exp.type = instanceExp;
1520                                     }
1521                                     break;
1522                                  }
1523                               }
1524                            }
1525                            */
1526                         }
1527                      }
1528                   }
1529                   if(!supported)
1530                   {
1531                      exp.type = memberPropertyErrorExp;
1532                      exp.isConstant = false;
1533                   }
1534                }
1535                else if(member)
1536                {
1537                   if(memberExp.hasAddress || memberExp.type == constantExp)
1538                   //if(memberExp.expType && memberExp.expType.kind == intType)  // && !exp.index.exp.expType.isSigned
1539                   {
1540                      if(_class.type == bitClass)
1541                      {
1542                         if(memberExp.type == constantExp)
1543                         {
1544                            // Unfinished business...
1545                            BitMember bitMember = (BitMember)member;
1546                            uint64 bits = 0;
1547                            GetUInt64(memberExp, &bits);
1548                            bits &= bitMember.mask;
1549                            bits >>= bitMember.pos;
1550
1551                            FreeExpression(exp.member.exp);
1552                            FreeIdentifier(exp.member.member);
1553
1554                            exp.constant = PrintUInt64(bits);
1555
1556                            exp.isConstant = true;
1557                            exp.type = constantExp;
1558                            exp.hasAddress = false;
1559                         }
1560                      }
1561                      else
1562                      {
1563                         char * evaluation = null;
1564                         ExpressionType evalError = dummyExp;
1565                         bool gotAddress = false;
1566                         uint64 address = 0;
1567                         Expression prev = exp.prev, next = exp.next;
1568                         char format;
1569                         int size;
1570                         Expression expNew;
1571                         TypeKind kind = dummyType;
1572                         Type dataType = member.dataType;
1573
1574                         if(!dataType)
1575                            dataType = member.dataType = ProcessTypeString(member.dataTypeString, false);
1576
1577                         if(dataType.kind == classType && dataType._class.registered &&
1578                               (dataType._class.registered.type == enumClass || dataType._class.registered.type == bitClass || dataType._class.registered.type == unitClass))
1579                         {
1580                            if(dataType._class.registered.dataTypeString)
1581                               dataType._class.registered.dataType = ProcessTypeString(dataType._class.registered.dataTypeString, false);
1582                            dataType = dataType._class.registered.dataType;
1583                            if(!dataType)
1584                               dataType = ProcessTypeString("int", false);
1585                         }
1586
1587                         size = ComputeTypeSize(member.dataType);
1588
1589                         format = GetGdbFormatChar(dataType);
1590                         //if(memberExp.address)
1591                         {
1592                            //GetInt(memberExp, &address);
1593                            //offset = member.offset;
1594
1595                            // TESTING NOHEAD HERE?
1596                            if(_class.type == normalClass || _class.type == noHeadClass || _class.type == systemClass)
1597                               offset += member._class.offset;
1598
1599                            // VERIFY THIS: (trying to fix primitive.type)
1600                            // if(memberExp.type == constantExp)
1601                            if(memberExp.hasAddress && (_class.type != normalClass && _class.type != noHeadClass && _class.type != systemClass))
1602                            {
1603                               address = memberExp.address;
1604                               gotAddress = true;
1605                            }
1606                            else if(memberExp.type == constantExp)
1607                               gotAddress = GetUInt64(memberExp, &address);
1608                            else
1609                            {
1610                               gotAddress = GetUInt64(memberExp, &address);
1611                               //printf("Unhandled !!\n");
1612
1613                               //printf("memberExp.hasAddress = %d\n", memberExp.hasAddress);
1614                               //printf("memberExp.type = %d\n", memberExp.type);
1615                               //printf("_class.name = %s, _class.type = %d\n", _class.name, _class.type);
1616                            }
1617
1618                            address += offset;
1619
1620                            if(!gotAddress)
1621                               exp.type = unknownErrorExp;
1622                            else if((dataType.kind == classType && dataType._class &&
1623                                  (!dataType._class.registered || dataType._class.registered.type == normalClass || dataType._class.registered.type == noHeadClass || dataType._class.registered.type == systemClass)) ||
1624                               (dataType.kind != classType && dataType.kind != arrayType && dataType.kind != structType && dataType.kind != unionType))
1625                            {
1626                               evaluation = Debugger::ReadMemory(address, size, format, &evalError);
1627                               if(evalError != dummyExp)
1628                               {
1629                                  exp.type = evalError;
1630                                  exp.constant = PrintHexUInt64(address);
1631                               }
1632                               else if(evaluation)
1633                               {
1634                                  //printf("evaluation = %s\n", evaluation);
1635                                  expNew = ParseExpressionString(evaluation);
1636                                  delete evaluation;
1637                                  expNew.destType = exp.expType;
1638                                  if(exp.expType)
1639                                     exp.expType.refCount++;
1640                                  //FreeType(memberExp.destType);
1641                                  FreeType(exp.expType);
1642                                  FreeType(exp.destType);
1643                                  FreeExpContents(exp);
1644                                  ProcessExpressionType(expNew);
1645                                  DebugComputeExpression(expNew);
1646                                  expNew.prev = prev;
1647                                  expNew.next = next;
1648                                  expNew.isConstant = true;
1649                                  expNew.address = address;
1650                                  expNew.hasAddress = true;
1651                                  *exp = *expNew;
1652                                  delete expNew;
1653                               }
1654                               else
1655                               {
1656                                  FreeExpContents(exp);
1657                                  exp.type = unknownErrorExp;
1658                               }
1659                            }
1660                            else
1661                            {
1662                               // TESTING THIS HERE...
1663                               exp.type = constantExp;
1664                               exp.constant = PrintHexUInt64(address);
1665
1666                               exp.address = address;
1667                               exp.hasAddress = true;
1668                               exp.isConstant = true;
1669                            }
1670                         }
1671                      }
1672                      //else
1673                      //   exp.type = ExpUnknownError;
1674
1675                      //FreeExpContents(exp);
1676                      //exp.constant = PrintUInt64(value);
1677                      //exp.type = constantExp;
1678                   }
1679                }
1680                else
1681                {
1682                   if(type && (type.kind == structType || type.kind == unionType))
1683                   {
1684                      uint offset = 0;
1685                      Type memberType = exp.member.member ? FindMemberAndOffset(type, exp.member.member.string, &offset) : null;
1686                      if(memberType)
1687                      {
1688                         char * evaluation = null;
1689                         ExpressionType evalError = dummyExp;
1690                         uint64 address = 0;
1691                         bool gotAddress = false;
1692                         Expression prev = exp.prev, next = exp.next;
1693                         char format;
1694                         int size = memberType.size;
1695                         Expression expNew;
1696                         Type dataType = memberType;
1697                         TypeKind kind = dummyType;
1698
1699                         if(dataType.kind == classType && dataType._class.registered &&
1700                               (dataType._class.registered.type == enumClass || dataType._class.registered.type == bitClass || dataType._class.registered.type == unitClass))
1701                            dataType = dataType._class.registered.dataType;
1702
1703                         format = GetGdbFormatChar(dataType);
1704
1705                         if(memberExp.hasAddress)
1706                         {
1707                            address = memberExp.address;
1708                            gotAddress = true;
1709                         }
1710                         else if(memberExp.type == constantExp)
1711                            gotAddress = GetUInt64(memberExp, &address);
1712
1713                         address += offset;
1714
1715                         if(!gotAddress)
1716                         {
1717                            FreeExpContents(exp);
1718                            exp.type = unknownErrorExp;
1719                         }
1720                         else if((dataType.kind == classType && dataType._class &&
1721                               (!dataType._class.registered || dataType._class.registered.type == normalClass || dataType._class.registered.type == noHeadClass || dataType._class.registered.type == systemClass)) ||
1722                            (dataType.kind != classType && dataType.kind != arrayType && dataType.kind != structType && dataType.kind != unionType))
1723                         {
1724                            evaluation = Debugger::ReadMemory(address, size, format, &evalError);
1725                            if(evalError != dummyExp)
1726                            {
1727                               exp.type = evalError;
1728                               exp.constant = PrintHexUInt64(address);
1729                            }
1730                            else if(evaluation)
1731                            {
1732                               expNew = ParseExpressionString(evaluation);
1733                               delete evaluation;
1734                               expNew.destType = exp.expType;
1735                               if(exp.expType)
1736                                  exp.expType.refCount++;
1737                               //FreeType(memberExp.destType);
1738                               FreeType(exp.expType);
1739                               FreeType(exp.destType);
1740                               FreeExpContents(exp);
1741                               ProcessExpressionType(expNew);
1742                               DebugComputeExpression(expNew);
1743                               expNew.prev = prev;
1744                               expNew.next = next;
1745                               expNew.isConstant = true;
1746                               expNew.address = address;
1747                               expNew.hasAddress = true;
1748                               *exp = *expNew;
1749                               delete expNew;
1750                            }
1751                            else
1752                            {
1753                               FreeExpContents(exp);
1754                               exp.type = unknownErrorExp;
1755                            }
1756                         }
1757                         else
1758                         {
1759                            FreeExpContents(exp);
1760
1761                            // TESTING THIS HERE...
1762                            exp.type = constantExp;
1763                            exp.constant = PrintHexUInt64(address);
1764
1765                            exp.address = address;
1766                            exp.hasAddress = true;
1767                            exp.isConstant = true;
1768                         }
1769                      }
1770                      else
1771                         exp.type = memberSymbolErrorExp;
1772                   }
1773                   else
1774                      exp.type = memberSymbolErrorExp;
1775                }
1776             }
1777
1778             //if(exp.type != memberExp)
1779             {
1780                //FreeExpression(memberExp);
1781                //FreeIdentifier(memberID);
1782             }
1783          }
1784          else
1785          {
1786             exp.type = memberSymbolErrorExp;
1787          }
1788          break;
1789       }
1790       case typeSizeExp:
1791       {
1792          Type type = ProcessType(exp.typeName.qualifiers, exp.typeName.declarator);
1793          FreeExpContents(exp);
1794          exp.constant = PrintUInt(ComputeTypeSize(type));
1795          exp.type = constantExp;
1796          FreeType(type);
1797          break;
1798       }
1799       case classSizeExp:
1800       {
1801          Symbol classSym = FindClass(exp._class.name);
1802          if(classSym && classSym.registered)
1803          {
1804             //exp.constant = PrintUInt(classSym.registered.size);
1805             //exp.type = constantExp;
1806
1807             char className[1024];
1808             sprintf(className, "__ecereClass_%s", classSym.string);
1809             FreeExpContents(exp);
1810             exp.type = pointerExp;
1811             exp.member.exp = MkExpIdentifier(MkIdentifier(className));
1812             exp.member.member = MkIdentifier("size");
1813          }
1814          break;
1815       }
1816       case castExp:
1817       {
1818          DebugComputeExpression(exp.cast.exp);
1819
1820          if(ExpressionIsError(exp.cast.exp)) //.type == ExpSymbolError
1821             CarryExpressionError(exp, exp.cast.exp);
1822          else
1823          {
1824             exp.hasAddress = exp.cast.exp.hasAddress;
1825             exp.address = exp.cast.exp.address;
1826             if(exp.cast.exp.type == constantExp && exp.expType)
1827             {
1828                Type type = exp.expType;
1829                if(type.kind == classType && type._class && type._class.registered)
1830                {
1831                   Class _class = type._class.registered;
1832                   if(_class.type == unitClass || _class.type == bitClass || _class.type == enumClass)
1833                   {
1834                      if(!_class.dataType)
1835                         _class.dataType = ProcessTypeString(_class.dataTypeString, false);
1836                      type = _class.dataType;
1837                   }
1838                   else if(_class.type == structClass && !type.byReference)
1839                   {
1840                      FreeExpContents(exp);
1841                      exp.type = unknownErrorExp;
1842                      break;
1843                   }
1844                }
1845
1846                switch(type.kind)
1847                {
1848                   case charType:
1849                      if(type.isSigned)
1850                      {
1851                         char value = 0;
1852                         if(GetChar(exp.cast.exp, &value))
1853                         {
1854                            FreeExpContents(exp);
1855                            exp.constant = PrintChar(value);
1856                            exp.type = constantExp;
1857                            exp.isConstant = true;
1858                         }
1859                      }
1860                      else
1861                      {
1862                         unsigned char value = 0;
1863                         if(GetUChar(exp.cast.exp, &value))
1864                         {
1865                            FreeExpContents(exp);
1866                            exp.constant = PrintUChar(value);
1867                            exp.type = constantExp;
1868                            exp.isConstant = true;
1869                         }
1870                      }
1871                      break;
1872                   case shortType:
1873                      if(type.isSigned)
1874                      {
1875                         short value = 0;
1876                         if(GetShort(exp.cast.exp, &value))
1877                         {
1878                            FreeExpContents(exp);
1879                            exp.constant = PrintShort(value);
1880                            exp.type = constantExp;
1881                            exp.isConstant = true;
1882                         }
1883                      }
1884                      else
1885                      {
1886                         unsigned short value = 0;
1887                         if(GetUShort(exp.cast.exp, &value))
1888                         {
1889                            FreeExpContents(exp);
1890                            exp.constant = PrintUShort(value);
1891                            exp.type = constantExp;
1892                            exp.isConstant = true;
1893                         }
1894                      }
1895                      break;
1896                   case intType:
1897                      if(type.isSigned)
1898                      {
1899                         int value = 0;
1900                         if(GetInt(exp.cast.exp, &value))
1901                         {
1902                            FreeExpContents(exp);
1903                            exp.constant = PrintInt(value);
1904                            exp.type = constantExp;
1905                            exp.isConstant = true;
1906                         }
1907                      }
1908                      else
1909                      {
1910                         unsigned int value = 0;
1911                         if(GetUInt(exp.cast.exp, &value))
1912                         {
1913                            FreeExpContents(exp);
1914                            exp.constant = PrintUInt(value);
1915                            exp.type = constantExp;
1916                            exp.isConstant = true;
1917                         }
1918                      }
1919                      break;
1920                   case int64Type:
1921                      if(type.isSigned)
1922                      {
1923                         int64 value = 0;
1924                         if(GetInt64(exp.cast.exp, &value))
1925                         {
1926                            FreeExpContents(exp);
1927                            exp.constant = PrintInt64(value);
1928                            exp.type = constantExp;
1929                            exp.isConstant = true;
1930                         }
1931                      }
1932                      else
1933                      {
1934                         uint64 value = 0;
1935                         if(GetUInt64(exp.cast.exp, &value))
1936                         {
1937                            FreeExpContents(exp);
1938                            exp.constant = PrintUInt64(value);
1939                            exp.type = constantExp;
1940                            exp.isConstant = true;
1941                         }
1942                      }
1943                      break;
1944                   case pointerType:
1945                   case classType:
1946                   {
1947                      uint64 value = 0;
1948                      if(GetUInt64(exp.cast.exp, &value))
1949                      {
1950                         FreeExpContents(exp);
1951                         if(type.kind == pointerType || type.kind == classType)
1952                            exp.constant = PrintHexUInt64(value);
1953                         else
1954                            exp.constant = PrintUInt64(value);
1955                         exp.type = constantExp;
1956                         exp.isConstant = true;
1957                      }
1958                      break;
1959                   }
1960                   case floatType:
1961                   {
1962                      float value = 0;
1963                      if(exp.cast.exp.type == constantExp && exp.cast.exp.constant &&
1964                         (!strcmpi(exp.cast.exp.constant, "nan") ||
1965                         !strcmpi(exp.cast.exp.constant, "-nan") ||
1966                         !strcmpi(exp.cast.exp.constant, "inf") ||
1967                         !strcmpi(exp.cast.exp.constant, "-inf")))
1968                      {
1969                         String constant = exp.cast.exp.constant;
1970                         exp.cast.exp.constant = null;
1971                         FreeExpContents(exp);
1972                         exp.constant = constant;
1973                         exp.type = constantExp;
1974                         exp.isConstant = true;
1975                      }
1976                      else if(GetFloat(exp.cast.exp, &value))
1977                      {
1978                         FreeExpContents(exp);
1979                         exp.constant = PrintFloat(value);
1980                         exp.type = constantExp;
1981                         exp.isConstant = true;
1982                      }
1983                      break;
1984                   }
1985                   case doubleType:
1986                   {
1987                      double value = 0;
1988                      if(exp.cast.exp.type == constantExp && exp.cast.exp.constant &&
1989                         (!strcmpi(exp.cast.exp.constant, "nan") ||
1990                         !strcmpi(exp.cast.exp.constant, "-nan") ||
1991                         !strcmpi(exp.cast.exp.constant, "inf") ||
1992                         !strcmpi(exp.cast.exp.constant, "-inf")))
1993                      {
1994                         String constant = exp.cast.exp.constant;
1995                         exp.cast.exp.constant = null;
1996                         FreeExpContents(exp);
1997                         exp.constant = constant;
1998                         exp.type = constantExp;
1999                         exp.isConstant = true;
2000                      }
2001                      else if(GetDouble(exp.cast.exp, &value))
2002                      {
2003                         FreeExpContents(exp);
2004                         exp.constant = PrintDouble(value);
2005                         exp.type = constantExp;
2006                         exp.isConstant = true;
2007                      }
2008                      break;
2009                   }
2010                }
2011             }
2012          }
2013          break;
2014       }
2015       case conditionExp:
2016       {
2017          if(exp.cond.cond)
2018          {
2019             DebugComputeExpression(exp.cond.cond);
2020
2021             if(ExpressionIsError(exp.cond.cond))
2022                CarryExpressionError(exp, exp.cond.cond);
2023             else if(exp.cond.cond.type == constantExp && exp.cond.cond.constant)
2024             {
2025                Expression e = null;
2026                if(strtol(exp.cond.cond.constant, null, 0))
2027                {
2028                   for(e = exp.cond.exp ? exp.cond.exp->first : null; e; e = e.next)
2029                   {
2030                      DebugComputeExpression(e);
2031                      if(!e.next) break;
2032                   }
2033                   if(e)
2034                   {
2035                      if(ExpressionIsError(e))
2036                      {
2037                         CarryExpressionError(exp, e);
2038                         e = null;
2039                      }
2040                      else
2041                         exp.cond.exp->Remove(e);
2042                   }
2043                }
2044                else
2045                {
2046                   e = exp.cond.elseExp;
2047                   if(e)
2048                   {
2049                      DebugComputeExpression(e);
2050                      if(ExpressionIsError(e))
2051                      {
2052                         CarryExpressionError(exp, e);
2053                         e = null;
2054                      }
2055                      else
2056                         exp.cond.elseExp = null;
2057                   }
2058                }
2059                if(e)
2060                {
2061                   FreeType(exp.expType);
2062                   FreeType(exp.destType);
2063                   e.prev = exp.prev;
2064                   e.next = exp.next;
2065                   FreeExpContents(exp);
2066                   *exp = *e;
2067                   delete e;
2068                }
2069                else if(!ExpressionIsError(exp))
2070                {
2071                   FreeExpContents(exp);
2072                   exp.type = unknownErrorExp;
2073                }
2074             }
2075             else
2076             {
2077                FreeExpContents(exp);
2078                exp.type = unknownErrorExp;
2079             }
2080          }
2081          else
2082          {
2083             FreeExpContents(exp);
2084             exp.type = unknownErrorExp;
2085          }
2086          break;
2087       }
2088    }
2089 }