ide/debugger; compiler/libec: (#19, #456) Fixed watches memory leaks, improved errors
[sdk] / ide / src / debugger / debugTools.ec
1 import "ide"
2
3 static void CarryExpressionError(Expression exp, Expression expError)
4 {
5    Expression temp { };
6
7    // This function assumes that expError is contained within exp,
8    // and therefore these types will be freed when freeing the old contents
9    // of the expression we're carying into.
10
11    if(expError.destType) expError.destType.refCount++;
12    if(expError.expType) expError.expType.refCount++;
13
14    *temp = *expError;
15
16    // -- Careful: this could be problematic as FreeExpContents will free the contents of expError
17    // Nulling things that may be freed now, but this is all overly messy/complex
18    switch(expError.type)
19    {
20       case symbolErrorExp:
21          expError.identifier = null;
22          break;
23       case memoryErrorExp:
24          expError.constant = null;
25          break;
26       case memberSymbolErrorExp:
27          expError.member.exp = null;
28          expError.member.member = null;
29          break;
30    }
31
32    /*
33    Identifier identifier = expError.identifier;
34    expError.identifier = null;
35    FreeExpContents(exp);
36    exp.identifier = identifier;
37    exp.type = expError.type;
38    */
39    if(exp.expType) FreeType(exp.expType);
40    if(exp.destType) FreeType(exp.destType);
41    FreeExpContents(exp);
42    *exp = *temp; //*expError;
43    delete temp;
44    // memset(expError, 0, sizeof(class Expression));
45 }
46
47 static char GetGdbFormatChar(Type type)
48 {
49 //          x : Regard the bits of the value as an integer, and print the integer in hexadecimal.
50 //          d : Print as integer in signed decimal.
51 //          u : Print as integer in unsigned decimal.
52 //          o : Print as integer in octal.
53 //          t : Print as integer in binary. The letter `t' stands for "two". (4)
54 //          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:
55 //          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.
56 //          f : Regard the bits of the value as a floating point number and print using typical floating point syntax.
57    if(!type)
58       return 'x';
59
60    switch(type.kind)
61    {
62       case charType:
63          //return 'c';
64       case shortType:
65       case intType:
66       case longType:
67       case int64Type:
68          if(type.isSigned)
69             return 'd';
70          else
71             return 'u';
72       case floatType:
73          return 'f';
74       case doubleType:
75          return 'f';
76       case structType:
77       case unionType:
78       case functionType:
79       case arrayType:
80          // return 'u';
81          return 0;
82       case ellipsisType:
83       case enumType:
84       case methodType:
85       case vaListType:
86       // case TypeTypedObject, TypeAnyObject, TypeClassPointer:
87       case dummyType:
88          break;
89       case classType:
90       case pointerType:
91          return 'x';
92    }
93    return 'x';
94 }
95
96 /*static */bool ExpressionIsError(Expression exp)
97 {
98    return (exp.type == dereferenceErrorExp || exp.type == symbolErrorExp ||
99          exp.type == memberSymbolErrorExp || exp.type == memoryErrorExp || exp.type == unknownErrorExp ||
100          exp.type == noDebuggerErrorExp);
101 }
102
103 void DebugComputeExpression(Expression exp)
104 {
105 #ifdef _DEBUG
106    char expString[1024] = "";
107    //char temp[1024];
108    //if(inCompiler)
109       PrintExpression(exp, expString);
110    // printf("%s (exp.type = %s)\n", expString, exp.type.OnGetString(temp, null, null));
111 #endif
112    switch(exp.type)
113    {
114       case identifierExp:
115       {
116          Expression prev = exp.prev, next = exp.next;
117          char * evaluation = null;
118          ExpressionType evalError = dummyExp;
119          Expression expNew;
120          TypeKind kind = dummyType;
121          Type dataType = exp.expType;
122
123          char temp[1024];
124          uint64 address;
125          bool hasAddress;
126          bool isPointer = false;
127
128          if(dataType && dataType.kind == classType && dataType._class.registered)
129          {
130             Class _class = dataType._class.registered;
131             if(_class.type == bitClass || _class.type == unitClass || _class.type == enumClass)
132             {
133                if(!_class.dataType)
134                   _class.dataType = ProcessTypeString(_class.dataTypeString, false);
135                dataType = _class.dataType;
136             }
137             else if(_class.type == normalClass || _class.type == noHeadClass || _class.type == systemClass) // Added systemClass here for Instance
138             {
139                isPointer = true;
140             }
141          }
142          else if(dataType && dataType.kind == classType && !dataType._class.registered)
143             isPointer = true;
144          if(dataType)
145             kind = dataType.kind;
146          else
147             exp.type = symbolErrorExp;
148          temp[0] = '\0';
149          switch(kind)
150          {
151             case intPtrType: case intSizeType: case _BoolType:
152             case charType: case shortType: case intType: case int64Type: case longType: case floatType: case doubleType:
153             case enumType:
154             case arrayType:
155             case structType:
156             case pointerType:
157             case unionType:
158                sprintf(temp, "&%s", exp.identifier.string);
159                break;
160             case classType:
161                if(exp.byReference && dataType._class && dataType._class.registered && dataType._class.registered.type == structClass)
162                // if(!dataType._class || !dataType._class.registered || dataType._class.registered.type != structClass || exp.byReference)
163                   strcpy(temp, exp.identifier.string);
164                else
165                   sprintf(temp, "&%s", exp.identifier.string);
166                break;
167             case functionType:
168             case ellipsisType:
169             case methodType:
170             case vaListType:
171             // case TypeTypedObject, TypeAnyObject, TypeClassPointer:
172             case dummyType:
173                break;
174          }
175          if(temp[0])
176          {
177             evaluation = Debugger::EvaluateExpression(temp, &evalError);
178             if(evaluation)
179             {
180                address = _strtoui64(evaluation, null, 0);
181                //delete evaluation;
182                //evaluation = null;
183             }
184             else
185                address = 0;
186             hasAddress = true;
187          }
188          else
189             hasAddress = false;
190
191          if(evalError == dummyExp)
192          {
193             switch(kind)
194             {
195                case charType:
196                   delete evaluation;
197                   evaluation = Debugger::EvaluateExpression(exp.identifier.string, &evalError);
198                   if(evaluation)
199                   {
200                      //int c, len;
201                      char * temp;
202                      temp = strstr(evaluation, " '");
203                      //len = strlen(temp);
204                      if(temp)
205                         temp[0] = '\0';
206                      {/*
207                         for(c = 0; c < len; c++)
208                            temp[c] = ' ';
209                         eString_TrimRSpaces(evaluation, evaluation);
210                      */}
211                   }
212                   break;
213                case shortType:
214                case intType:
215                case longType:
216                case intPtrType:
217                case intSizeType:
218                case _BoolType:
219                case int64Type:
220                case floatType:
221                case doubleType:
222                case enumType:
223                case pointerType:
224                   delete evaluation;
225                   evaluation = Debugger::EvaluateExpression(exp.identifier.string, &evalError);
226                   if(evaluation)
227                   {
228                      if(kind == pointerType)
229                      {
230                         uint64 value;
231                         value = _strtoui64(evaluation, null, 0);
232                         delete evaluation;
233                         evaluation = PrintHexUInt64(value);
234                      }
235                   }
236                   break;
237                case classType:
238                   if(isPointer)
239                   {
240                      int size;
241                      char format;
242                      delete evaluation;
243                      //evaluation = Debugger::EvaluateExpression(exp.identifier.string, &evalError);
244                      size = ComputeTypeSize(exp.expType); //exp.expType.arrayType.size;
245                      format = GetGdbFormatChar(exp.expType);
246                      evaluation = Debugger::ReadMemory(address, size, format, &evalError);
247                      if(evaluation)
248                         StripQuotes(evaluation, evaluation);
249                   }
250                   break;
251                case structType:
252                case unionType:
253                case functionType:
254                   //evaluation = Debugger::EvaluateExpression(exp.identifier.string, &evalError);
255                   delete evaluation;
256                   break;
257                case arrayType:
258                {
259                   // for classType  --> if(_class.type == structClass) ?
260                   //char temp[1024];
261                   //sprintf(temp, "&%s", exp.identifier.string);
262                   //evaluation = Debugger::EvaluateExpression(temp, &evalError);
263                   break;
264                }
265                case ellipsisType:
266                case methodType:
267                case vaListType:
268                // case TypeTypedObject, TypeAnyObject, TypeClassPointer:
269                case dummyType:
270                   delete evaluation;
271                   evaluation = Debugger::EvaluateExpression(exp.identifier.string, &evalError);
272                   break;
273             }
274          }
275          switch(evalError)
276          {
277             case dummyExp:
278                if(evaluation)
279                {
280                   //expNew = ParseExpressionString(evaluation);
281                   expNew = MkExpConstant(evaluation);
282                   //printf("Evaluation = %s\n", evaluation);
283                   delete evaluation;
284                   expNew.destType = exp.expType;
285
286                   // WHY EXACTLY MUST WE PROCESS THIS EXPRESSION TYPE AGAIN ? ADDED THIS FOR 0x00000000
287                   if(exp.expType && (exp.expType.kind == pointerType || exp.expType.kind == classType) && expNew.destType)
288                   {
289                      expNew.expType = expNew.destType;
290                      expNew.destType.refCount++;
291                   }
292                   else
293                      ProcessExpressionType(expNew);
294                   FreeType(exp.destType);
295                   FreeExpContents(exp);
296
297                   DebugComputeExpression(expNew);
298                   expNew.prev = prev;
299                   expNew.next = next;
300                   expNew.isConstant = true;
301                   expNew.address = address;
302                   expNew.hasAddress = hasAddress;
303                   *exp = *expNew;
304                   delete expNew;
305                }
306                else
307                {
308                   // Unhandled code path, evaluation is null
309                   FreeExpContents(exp);
310                   exp.type = unknownErrorExp;
311                }
312                break;
313             case symbolErrorExp:
314                // Keep the identifier
315                exp.type = evalError;
316                break;
317             default:
318                FreeExpContents(exp);
319                exp.type = evalError;
320                break;
321          }
322          break;
323       }
324       case instanceExp:
325       {
326          ComputeInstantiation(exp);
327          break;
328       }
329       /*
330       case constantExp:
331          break;
332       */
333       case opExp:
334       {
335          Expression expError = null;
336          Expression exp1, exp2 = null;
337          Operand op1 = { 0 }, op2 = { 0 };
338
339          /*
340          if(exp.op.op == '&' || exp.op.op == '*')
341          {
342             if(!exp.op.exp1 && exp.op.exp2)
343             {
344                if(exp.op.exp2.type == identifierExp)
345                {
346                   Expression prev = exp.prev, next = exp.next;
347                   char * evaluation = null;
348                   ExpressionType evalError = dummyExp;
349                   Expression expNew;
350                   char temp[1024];
351                   sprintf(temp, "%c%s", exp.op.op, exp.op.exp2.identifier.string);
352                   evaluation = Debugger::EvaluateExpression(temp, &evalError);
353                   if(evalError != dummyExp)
354                   {
355                      exp.type = evalError;
356                      exp.constant = CopyString("");
357                   }
358                   else if(evaluation)
359                   {
360                      expNew = ParseExpressionString(evaluation);
361                      delete evaluation;
362                      expNew.destType = exp.expType;
363                      FreeType(exp.destType);
364                      FreeExpContents(exp);
365                      ProcessExpressionType(expNew);
366                      DebugComputeExpression(expNew);
367                      expNew.prev = prev;
368                      expNew.next = next;
369                      expNew.isConstant = true;
370                      *exp = *expNew;
371                      delete expNew;
372                   }
373                   else
374                      exp.type = ExpUnknownError;
375                   break;
376                }
377                //else
378                {
379                   uint64 address;
380                   int size;
381                   char format;
382                   if(exp.op.op == '*')
383                   {
384                   DebugComputeExpression(exp.op.exp2);
385                   size = ComputeTypeSize(exp.op.exp2.expType);
386                   format = GetGdbFormatChar(exp.op.exp2.expType);
387                   GetInt(exp.op.exp2, &address);
388                   //sprintf(temp, "%c%s", exp.op.op, exp.op.exp2.constant);
389                   evaluation = Debug_ReadMemory(address, size, format, &evalError);
390                   }
391                   else
392                      evalError = ExpUnknownError;
393                }
394             }
395          }
396          */
397
398          // We don't care about operations with only exp2 (INC_OP, DEC_OP...)
399          if(exp.op.exp2)
400          {
401             DebugComputeExpression(exp.op.exp2);
402             if(ExpressionIsError(exp.op.exp2))
403                expError = exp.op.exp2;
404          }
405          if(!expError)
406          {
407             if(exp.op.exp1)
408             {
409                DebugComputeExpression(exp.op.exp1);
410                if(ExpressionIsError(exp.op.exp1))
411                   expError = exp.op.exp1;
412                else
413                {
414                   if(exp.op.exp2)
415                   {
416                      if(ExpressionIsError(exp.op.exp2))
417                         expError = exp.op.exp2;
418                      else
419                      {
420                         exp1 = exp.op.exp1;
421                         exp2 = exp.op.exp2;
422                         op1 = GetOperand(exp1);
423                         if(op1.type) op1.type.refCount++;
424                         op2 = GetOperand(exp2);
425                         if(op2.type) op2.type.refCount++;
426                      }
427                   }
428                }
429             }
430             else if(exp.op.exp2)
431             {
432                if(ExpressionIsError(exp.op.exp2))
433                   expError = exp.op.exp2;
434                else
435                {
436                   exp1 = exp.op.exp2;
437                   if(exp.op.op == '&' || exp.op.op == '*')
438                   {
439                      Expression prev = exp1.prev, next = exp1.next;
440                      Expression expNew;
441                      ExpressionType evalError = dummyExp;
442                      char * evaluation = null;
443                      if(exp.op.op == '&')
444                      {
445                         if(exp1.hasAddress)
446                         {
447                            char * temp;
448                            //sprintf(temp, "%u", exp1.address);
449                            temp = PrintHexUInt64(exp1.address);
450                            expNew = ParseExpressionString(temp);
451                            delete temp;
452                            //expNew.address = exp1.address;
453                            expNew.expType = exp.expType;
454                            /*
455                            expNew.destType = exp.expType;
456                            expNew.destType.refCount++;
457                            */
458                            FreeType(exp.destType);
459                            FreeExpContents(exp);
460                            ProcessExpressionType(expNew);
461                            DebugComputeExpression(expNew);
462                            expNew.prev = prev;
463                            expNew.next = next;
464                            expNew.isConstant = true;
465                            *exp = *expNew;
466                            delete expNew;
467                         }
468                         else
469                            exp1.address = 0;
470                      }
471                      else if(exp.op.op == '*')
472                      {
473                         if(!exp.expType)
474                         {
475                            delete evaluation;
476                            FreeExpContents(exp1);
477                            exp1.type = dereferenceErrorExp;
478                            expError = exp1;
479                         }
480                         else
481                         {
482                            uint64 address;
483                            int size;
484                            char format;
485                            if(exp1.expType.kind == structType)
486                               address = exp1.address;
487                            else
488                               GetUInt64(exp1, &address);
489                            size = ComputeTypeSize(exp.expType); //exp.expType.arrayType.size;
490                            format = GetGdbFormatChar(exp.expType);
491                            if(format)
492                            {
493                               evaluation = Debugger::ReadMemory(address, size, format, &evalError);
494                               switch(evalError)
495                               {
496                                  case dummyExp:
497                                     if(evaluation)
498                                     {
499                                        expNew = ParseExpressionString(evaluation);
500                                        expNew.address = address;
501                                        expNew.hasAddress = true;
502                                        delete evaluation;
503                                        expNew.destType = exp.expType;
504                                        FreeType(exp.destType);
505                                        FreeExpContents(exp);
506                                        ProcessExpressionType(expNew);
507                                        DebugComputeExpression(expNew);
508                                        expNew.prev = prev;
509                                        expNew.next = next;
510                                        expNew.isConstant = true;
511                                        *exp = *expNew;
512                                        delete expNew;
513                                     }
514                                     else
515                                     {
516                                        // Unhandled code path, evaluation is null
517                                        FreeExpContents(exp);
518                                        exp.type = unknownErrorExp;
519                                     }
520                                     break;
521                                  case memoryErrorExp:
522                                     delete evaluation;
523                                     FreeExpContents(exp1);
524                                     exp1.type = evalError;
525                                     exp1.constant = PrintHexUInt64(address);
526                                     expError = exp1;
527                                     break;
528                                  default:
529                                     delete evaluation;
530                                     FreeExpContents(exp1);
531                                     exp1.type = evalError;
532                                     expError = exp1;
533                                     break;
534
535                               }
536                            }
537                            else
538                            {
539                               FreeExpContents(exp1);
540                               exp1.type = unknownErrorExp;  // Not supported yet, generate error to fallback to GDB printout
541                               expError = exp1;
542                            }
543                         }
544                      }
545                   }
546                   else
547                      op1 = GetOperand(exp1);
548                   if(op1.type) op1.type.refCount++;
549                }
550             }
551          }
552          if(expError)
553             CarryExpressionError(exp, expError);
554          else if(exp.type == opExp)
555          {
556             // TODO: check condition
557             if((exp.op.op == '+' || exp.op.op == '-') && op1.type && op2.type &&
558                (op1.type.kind == arrayType || op1.type.kind == pointerType) && op2.type.kind == intType)
559             {
560                // TODO: Do pointer operations
561                if(exp1.expType && exp1.expType.type)
562                {
563                   if(exp1.type == stringExp)
564                   {
565                      int len = exp1.string ? strlen(exp1.string)-2 : 0;
566                      uint64 offset = (exp.op.op == '+') ? op2.i64 : -op2.i64;
567                      String newString = null;
568                      if(len >= 0 && offset <= len)
569                      {
570                         newString = new char[3 + len - offset];
571                         newString[0] = '\"';
572                         memcpy(newString + 1, exp1.string + 1 + offset, len - offset);
573                         newString[1 + len - offset] = '\"';
574                         newString[1 + len - offset + 1] = 0;
575                      }
576                      FreeExpContents(exp);
577                      if(newString)
578                      {
579                         exp.type = stringExp;
580                         exp.string = newString;
581                      }
582                      else
583                         exp.type = dereferenceErrorExp;
584                   }
585                   else
586                   {
587                      uint size = ComputeTypeSize(exp1.expType.type);
588                      if(size)
589                      {
590                         op1.ui64 /= exp1.expType.type.size;
591                         CallOperator(exp, exp1, exp2, op1, op2);
592                         if(exp.type == constantExp)
593                         {
594                            exp.address = _strtoui64(exp.constant, null, 0);
595                            exp.address *= size;
596                            if(op1.type.kind == arrayType)
597                               exp.hasAddress = true;
598                         }
599                      }
600                   }
601                }
602             }
603             else
604             {
605                if((exp1 && exp1.type == stringExp) || (exp2 && exp2.type == stringExp))
606                {
607                   FreeExpContents(exp);
608                   exp.type = unknownErrorExp;   // We should have an invalid operands error
609                }
610                else
611                   CallOperator(exp, exp1, exp2, op1, op2);
612             }
613             if(op1.type) FreeType(op1.type);
614             if(op2.type) FreeType(op2.type);
615             exp.isConstant = true;
616          }
617          break;
618       }
619       case bracketsExp:
620       {
621          Expression e, n;
622          //for(
623          //   e = (*exp.list).first, n = e ? e.next : null;
624          //   e;
625          //   e = n, n = n?(n.next) : null)
626
627          for(e = exp.list->first; e; e = n)
628          {
629             n = e.next;
630             if(!n)
631             {
632                OldList * list = exp.list;
633                DebugComputeExpression(e);
634                //if(ExpressionIsError(e)) //.type == ExpSymbolError
635                //   CarryExpressionError(exp, e);
636                //FreeExpContents(exp);
637                FreeType(exp.expType);
638                FreeType(exp.destType);
639                *exp = *e;
640                delete e;
641                delete list;
642             }
643             else
644             {
645                FreeExpression(e);
646             }
647          }
648          break;
649       }
650       case indexExp:
651       {
652          int size;
653          char format;
654          Expression e;
655          exp.isConstant = true;
656
657          DebugComputeExpression(exp.index.exp);
658          if(ExpressionIsError(exp.index.exp)) //.type == ExpSymbolError
659             CarryExpressionError(exp, exp.index.exp);
660          else
661          {
662             Expression prev = exp.prev, next = exp.next;
663             char * evaluation = null;
664             ExpressionType evalError = dummyExp;
665
666             if(!exp.index.exp.isConstant)
667                exp.isConstant = false;
668
669             // int r[0]
670             // 4 == size = ComputeTypeSize(exp.expType);
671             // 0 == size = ComputeTypeSize(exp.expType.arrayType);
672             // 4 == size = ComputeTypeSize(exp.index.exp.expType);
673             // 0 == size = ComputeTypeSize(exp.index.exp.expType.arrayType);
674
675             size = ComputeTypeSize(exp.expType);
676             if(exp.expType && exp.expType.type && exp.expType.kind == arrayType)
677                // For multilevels arrays
678                format = 'x';
679             else
680                format = GetGdbFormatChar(exp.expType);
681
682             for(e = exp.index.index->first; e; e = e.next)
683             {
684                DebugComputeExpression(e);
685                if(ExpressionIsError(e)) //.type == ExpSymbolError
686                {
687                   CarryExpressionError(exp, e);
688                   break;
689                }
690                if(!e.next)
691                {
692                   // Check if this type is int
693                }
694                if(!e.isConstant)
695                   exp.isConstant = false;
696             }
697             if(!ExpressionIsError(exp))
698             {
699                // Is this necessary here? pass15 had done this already...
700                if(exp.expType) FreeType(exp.expType);
701                exp.expType = Dereference(exp.index.exp.expType);
702
703                if(!exp.expType)
704                {
705                   delete evaluation;
706                   FreeExpContents(exp);
707                   exp.type = dereferenceErrorExp;
708                }
709                else if(exp.index.index && exp.index.index->last && ((Expression)exp.index.index->last) && ((Expression)exp.index.index->last).expType)
710                {
711                   Type type = ((Expression)exp.index.index->last).expType;
712                   if(type.kind == intType || type.kind == charType || type.kind == shortType || type.kind == int64Type || type.kind == intPtrType ||
713                      type.kind == intSizeType || type.kind == longType || type.kind == _BoolType || type.kind == enumType ||
714                         (type.kind == classType && type._class && type._class.registered &&
715                            type._class.registered.type == enumClass))
716                   {
717                      uint64 address = 0, offset = 0;
718                      Expression expNew, last = (Expression)exp.index.index->last;
719                      //GetUInt(exp.index.exp, &address);
720
721                      // TOFIX: Check if it has address: TESTING
722                      if(exp.index.exp.hasAddress && (exp.index.exp.expType.kind == arrayType))
723                         address = exp.index.exp.address;
724                      else if(exp.index.exp.type == constantExp)
725                         GetUInt64(exp.index.exp, &address);
726
727                      GetUInt64(last, &offset);
728                      //size = ComputeTypeSize(exp.expType.arrayType); //exp.expType.arrayType.size;
729                      address += offset * size;
730                      if(exp.index.exp.type == stringExp)
731                      {
732                         String string = exp.index.exp.string;
733                         int len = string ? strlen(string)-2 : 0;
734                         bool valid = false;
735                         char ch = 0;
736                         if(len >= 0 && offset <= len)
737                         {
738                            ch = offset < len ? string[1 + offset] : 0;
739                            valid = true;
740                         }
741                         FreeExpContents(exp);
742                         if(valid)
743                         {
744                            exp.type = constantExp;
745                            exp.constant = PrintChar(ch);
746                         }
747                         else
748                            exp.type = dereferenceErrorExp;
749                      }
750                      else if(exp.expType.kind == arrayType)
751                      {
752                         FreeExpContents(exp);
753                         exp.type = constantExp;
754                         exp.isConstant = true;
755                         exp.constant = PrintHexUInt64(address);
756                         exp.address = address;
757                         exp.hasAddress = true;
758                      }
759                      else
760                      {
761                         evaluation = Debugger::ReadMemory(address, size, format, &evalError);
762                         switch(evalError)
763                         {
764                            case dummyExp:
765                               if(evaluation)
766                               {
767                                  expNew = ParseExpressionString(evaluation);
768                                  delete evaluation;
769                                  expNew.destType = exp.expType;
770                                  FreeType(exp.destType);
771                                  FreeExpContents(exp);
772                                  ProcessExpressionType(expNew);
773                                  DebugComputeExpression(expNew);
774
775                                  // TOFIX: Only for Array Types
776                                  expNew.address = address;
777
778                                  expNew.hasAddress = true;
779                                  expNew.prev = prev;
780                                  expNew.next = next;
781                                  expNew.isConstant = true;
782                                  *exp = *expNew;
783                                  delete expNew;
784                               }
785                               else
786                               {
787                                  // Unhandled code path, evaluation is null
788                                  FreeExpContents(exp);
789                                  exp.type = unknownErrorExp;
790                               }
791                               break;
792                            case memoryErrorExp:
793                               delete evaluation;
794                               FreeExpContents(exp);
795                               exp.type = evalError;
796                               exp.constant = PrintHexUInt64(address);
797                               break;
798                            default:
799                               delete evaluation;
800                               FreeExpContents(exp);
801                               exp.type = evalError;
802                               break;
803                         }
804                      }
805                   }
806                }
807             }
808          }
809          break;
810       }
811       case memberExp:
812       {
813          Expression memberExp = exp.member.exp;
814          Identifier memberID = exp.member.member;
815          //Class _class;
816          Property prop = null;
817          DataMember member = null;
818          Class convertTo = null;
819          uint offset = 0;  // THIS WASN'T INITIALIZED... IS IT ALWAYS SET?
820
821          Type type; // = memberExp.expType;
822          DebugComputeExpression(memberExp);
823          type = memberExp.expType;
824          if(ExpressionIsError(memberExp))
825             CarryExpressionError(exp, memberExp);
826          else if(type)
827          {
828             // _class = (memberID && memberID.classSym) ? memberID.classSym.registered : ((type.kind == classType && type._class) ? type._class.registered : null);
829             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);
830             if(!_class)
831             {
832                char string[256] = "";
833                Symbol classSym;
834                PrintTypeNoConst(type, string, false, true);
835                classSym = FindClass(string);
836                _class = classSym ? classSym.registered : null;
837             }
838
839             if(memberID && _class)
840             {
841                /*
842                prop = eClass_FindProperty(_class, memberID.string);
843                if(!prop)
844                   member = eClass_FindDataMember(_class, memberID.string);
845                */
846                // member = eClass_FindDataMember(_class, memberID.string);
847                member = eClass_FindDataMemberAndOffset(_class, memberID.string, &offset, _class.module.application, null, null);
848                if(!member)
849                   prop = eClass_FindProperty(_class, memberID.string, _class.module.application);
850             }
851             if(!prop && !member && _class && memberID)
852             {
853                Symbol classSym = FindClass(memberID.string);
854                convertTo = _class;
855                _class = classSym ? classSym.registered : null;
856                if(_class)
857                   prop = eClass_FindProperty(_class, convertTo.name, _class.module.application);
858             }
859
860             //DebugComputeExpression(memberExp);
861             if(ExpressionIsError(memberExp))
862                CarryExpressionError(exp, memberExp);
863             else
864             {
865                if(prop)
866                {
867                   if(prop.compiled)
868                   {
869                      Type type = prop.dataType;
870                      // TODO: Assuming same base type for units...
871                      if(_class.type == unitClass)
872                      {
873                         if(type.kind == classType)
874                         {
875                            Class _class = type._class.registered;
876                            if(_class.type == unitClass)
877                            {
878                               if(!_class.dataType)
879                                  _class.dataType = ProcessTypeString(_class.dataTypeString, false);
880                               type = _class.dataType;
881                            }
882                         }
883                         switch(type.kind)
884                         {
885                            case floatType:
886                            {
887                               float value;
888                               float (*Get)(float) = (void *)prop.Get;
889                               GetFloat(memberExp, &value);
890                               exp.constant = PrintFloat(Get ? Get(value) : value);
891                               exp.type = constantExp;
892                               break;
893                            }
894                            case doubleType:
895                            {
896                               double value;
897                               double (*Get)(double);
898                               GetDouble(memberExp, &value);
899
900                               if(convertTo)
901                                  Get = (void *)prop.Set;
902                               else
903                                  Get = (void *)prop.Get;
904                               exp.constant = PrintDouble(Get ? Get(value) : value);
905                               exp.type = constantExp;
906                               break;
907                            }
908                         }
909                      }
910                      else
911                      {
912                         if(convertTo)
913                         {
914                            Expression value = memberExp;
915                            Type type = prop.dataType;
916                            if(_class.type == structClass)
917                            {
918                               switch(type.kind)
919                               {
920                                  case classType:
921                                  {
922                                     Class propertyClass = type._class.registered;
923                                     if(propertyClass.type == structClass && value.type == instanceExp)
924                                     {
925                                        void (*Set)(void *, void *) = (void *)prop.Set;
926                                        exp.instance = Instantiation
927                                        {
928                                           data = new0 byte[_class.structSize];
929                                           _class = MkSpecifierName/*MkClassName*/(_class.name);
930                                           loc = exp.loc;
931                                           exp.type = instanceExp;
932                                        };
933                                        Set(exp.instance.data, value.instance.data);
934                                        PopulateInstance(exp.instance);
935                                     }
936                                     break;
937                                  }
938                                  case intType:
939                                  {
940                                     int intValue;
941                                     void (*Set)(void *, int) = (void *)prop.Set;
942
943                                     exp.instance = Instantiation
944                                     {
945                                        data = new0 byte[_class.structSize];
946                                        _class = MkSpecifierName/*MkClassName*/(_class.name);
947                                        loc = exp.loc;
948                                     };
949                                     exp.type = instanceExp;
950
951                                     GetInt(value, &intValue);
952
953                                     Set(exp.instance.data, intValue);
954                                     PopulateInstance(exp.instance);
955                                     break;
956                                  }
957                                  case int64Type:
958                                  {
959                                     int64 intValue;
960                                     void (*Set)(void *, int64) = (void *)prop.Set;
961
962                                     exp.instance = Instantiation
963                                     {
964                                        data = new0 byte[_class.structSize];
965                                        _class = MkSpecifierName/*MkClassName*/(_class.name);
966                                        loc = exp.loc;
967                                     };
968                                     exp.type = instanceExp;
969
970                                     GetInt64(value, &intValue);
971
972                                     Set(exp.instance.data, intValue);
973                                     PopulateInstance(exp.instance);
974                                     break;
975                                  }
976                                  case doubleType:
977                                  {
978                                     double doubleValue;
979                                     void (*Set)(void *, double) = (void *)prop.Set;
980
981                                     exp.instance = Instantiation
982                                     {
983                                        data = new0 byte[_class.structSize];
984                                        _class = MkSpecifierName/*MkClassName*/(_class.name);
985                                        loc = exp.loc;
986                                     };
987                                     exp.type = instanceExp;
988
989                                     GetDouble(value, &doubleValue);
990
991                                     Set(exp.instance.data, doubleValue);
992                                     PopulateInstance(exp.instance);
993                                     break;
994                                  }
995                               }
996                            }
997                            else if(_class.type == bitClass)
998                            {
999                               switch(type.kind)
1000                               {
1001                                  case classType:
1002                                  {
1003                                     Class propertyClass = type._class.registered;
1004                                     if(propertyClass.type == structClass && value.instance.data)
1005                                     {
1006                                        unsigned int (*Set)(void *) = (void *)prop.Set;
1007                                        unsigned int bits = Set(value.instance.data);
1008                                        exp.constant = PrintHexUInt(bits);
1009                                        exp.type = constantExp;
1010                                        break;
1011                                     }
1012                                     else if(_class.type == bitClass)
1013                                     {
1014                                        unsigned int value;
1015                                        unsigned int (*Set)(unsigned int) = (void *)prop.Set;
1016                                        unsigned int bits;
1017
1018                                        GetUInt(memberExp, &value);
1019                                        bits = Set(value);
1020                                        exp.constant = PrintHexUInt(bits);
1021                                        exp.type = constantExp;
1022                                     }
1023                                  }
1024                               }
1025                            }
1026                         }
1027                         else
1028                         {
1029                            if(_class.type == bitClass)
1030                            {
1031                               uint value;
1032                               GetUInt(memberExp, &value);
1033
1034                               switch(type.kind)
1035                               {
1036                                  case classType:
1037                                  {
1038                                     Class _class = type._class.registered;
1039                                     if(_class.type == structClass)
1040                                     {
1041                                        void (*Get)(unsigned int, void *) = (void *)prop.Get;
1042
1043                                        exp.instance = Instantiation
1044                                        {
1045                                           data = new0 byte[_class.structSize];
1046                                           _class = MkSpecifierName/*MkClassName*/(_class.name);
1047                                           loc = exp.loc;
1048                                        };
1049                                        //exp.instance.fullSet = true;
1050                                        exp.type = instanceExp;
1051                                        Get(value, exp.instance.data);
1052                                        PopulateInstance(exp.instance);
1053                                     }
1054                                     else if(_class.type == bitClass)
1055                                     {
1056                                        unsigned int (*Get)(unsigned int) = (void *)prop.Get;
1057                                        uint64 bits = Get(value);
1058                                        exp.constant = PrintHexUInt64(bits);
1059                                        exp.type = constantExp;
1060                                     }
1061                                     break;
1062                                  }
1063                               }
1064                            }
1065                            else if(_class.type == structClass)
1066                            {
1067                               char * value = (memberExp.type == instanceExp ) ? memberExp.instance.data : null;
1068                               switch(type.kind)
1069                               {
1070                                  case classType:
1071                                  {
1072                                     Class _class = type._class.registered;
1073                                     if(_class.type == structClass && value)
1074                                     {
1075                                        void (*Get)(void *, void *) = (void *)prop.Get;
1076
1077                                        exp.instance = Instantiation
1078                                        {
1079                                           data = new0 byte[_class.structSize];
1080                                           _class = MkSpecifierName/*MkClassName*/(_class.name);
1081                                           loc = exp.loc;
1082                                        };
1083                                        //exp.instance.fullSet = true;
1084                                        exp.type = instanceExp;
1085                                        Get(value, exp.instance.data);
1086                                        PopulateInstance(exp.instance);
1087                                     }
1088                                     break;
1089                                  }
1090                               }
1091                            }
1092                            /*else
1093                            {
1094                               char * value = memberExp.instance.data;
1095                               switch(type.kind)
1096                               {
1097                                  case classType:
1098                                  {
1099                                     Class _class = type._class.registered;
1100                                     if(_class.type == normalClass)
1101                                     {
1102                                        void *(*Get)(void *) = (void *)prop.Get;
1103
1104                                        exp.instance = Instantiation
1105                                        {
1106                                           data = Get(value, exp.instance.data);     ?????
1107                                           _class = MkSpecifierName(_class.name); //MkClassName(_class.name);
1108                                           loc = exp.loc;
1109                                        };
1110                                        exp.type = instanceExp;
1111                                     }
1112                                     break;
1113                                  }
1114                               }
1115                            }
1116                            */
1117                         }
1118                      }
1119                   }
1120                   else
1121                   {
1122                      exp.isConstant = false;
1123                   }
1124                }
1125                else if(member)
1126                {
1127                   if(memberExp.hasAddress || memberExp.type == constantExp)
1128                   //if(memberExp.expType && memberExp.expType.kind == intType)  // && !exp.index.exp.expType.isSigned
1129                   {
1130                      if(_class.type == bitClass)
1131                      {
1132                         if(memberExp.type == constantExp)
1133                         {
1134                            // Unfinished business...
1135                            BitMember bitMember = (BitMember)member;
1136                            uint64 bits;
1137                            GetUInt64(memberExp, &bits);
1138                            bits &= bitMember.mask;
1139                            bits >>= bitMember.pos;
1140
1141                            FreeExpression(exp.member.exp);
1142                            FreeIdentifier(exp.member.member);
1143
1144                            exp.constant = PrintUInt64(bits);
1145
1146                            exp.isConstant = true;
1147                            exp.type = constantExp;
1148                            exp.hasAddress = false;
1149                         }
1150                      }
1151                      else
1152                      {
1153                         char * evaluation = null;
1154                         ExpressionType evalError = dummyExp;
1155                         uint64 address;
1156                         Expression prev = exp.prev, next = exp.next;
1157                         char format;
1158                         int size;
1159                         Expression expNew;
1160                         TypeKind kind = dummyType;
1161                         Type dataType = member.dataType;
1162
1163                         if(!dataType)
1164                            dataType = member.dataType = ProcessTypeString(member.dataTypeString, false);
1165
1166                         if(dataType.kind == classType && dataType._class.registered &&
1167                               (dataType._class.registered.type == enumClass || dataType._class.registered.type == bitClass || dataType._class.registered.type == unitClass))
1168                         {
1169                            if(dataType._class.registered.dataTypeString)
1170                               dataType._class.registered.dataType = ProcessTypeString(dataType._class.registered.dataTypeString, false);
1171                            dataType = dataType._class.registered.dataType;
1172                            if(!dataType)
1173                               dataType = ProcessTypeString("int", false);
1174                         }
1175
1176                         size = ComputeTypeSize(member.dataType);
1177
1178                         format = GetGdbFormatChar(dataType);
1179                         //if(memberExp.address)
1180                         {
1181                            //GetInt(memberExp, &address);
1182                            //offset = member.offset;
1183
1184                            // TESTING NOHEAD HERE?
1185                            if(_class.type == normalClass || _class.type == noHeadClass || _class.type == systemClass)
1186                               offset += member._class.offset;
1187
1188                            // VERIFY THIS: (trying to fix primitive.type)
1189                            // if(memberExp.type == constantExp)
1190                            if(memberExp.hasAddress && (_class.type != normalClass && _class.type != noHeadClass && _class.type != systemClass))
1191                               address = memberExp.address;
1192                            else if(memberExp.type == constantExp)
1193                               GetUInt64(memberExp, &address);
1194                            else
1195                            {
1196                               address = 0;
1197                               GetUInt64(memberExp, &address);
1198                               //printf("Unhandled !!\n");
1199
1200                               //printf("memberExp.hasAddress = %d\n", memberExp.hasAddress);
1201                               //printf("memberExp.type = %d\n", memberExp.type);
1202                               //printf("_class.name = %s, _class.type = %d\n", _class.name, _class.type);
1203                            }
1204
1205                            address += offset;
1206
1207                            if((dataType.kind == classType && dataType._class &&
1208                                  (!dataType._class.registered || dataType._class.registered.type == normalClass || dataType._class.registered.type == noHeadClass || dataType._class.registered.type == systemClass)) ||
1209                               (dataType.kind != classType && dataType.kind != arrayType && dataType.kind != structType && dataType.kind != unionType))
1210                            {
1211                               evaluation = Debugger::ReadMemory(address, size, format, &evalError);
1212                               if(evalError != dummyExp)
1213                               {
1214                                  exp.type = evalError;
1215                                  exp.constant = PrintHexUInt64(address);
1216                               }
1217                               else if(evaluation)
1218                               {
1219                                  //printf("evaluation = %s\n", evaluation);
1220                                  expNew = ParseExpressionString(evaluation);
1221                                  delete evaluation;
1222                                  expNew.destType = exp.expType;
1223                                  if(exp.expType)
1224                                     exp.expType.refCount++;
1225                                  //FreeType(memberExp.destType);
1226                                  FreeType(exp.expType);
1227                                  FreeType(exp.destType);
1228                                  FreeExpContents(exp);
1229                                  ProcessExpressionType(expNew);
1230                                  DebugComputeExpression(expNew);
1231                                  expNew.prev = prev;
1232                                  expNew.next = next;
1233                                  expNew.isConstant = true;
1234                                  expNew.address = address;
1235                                  expNew.hasAddress = true;
1236                                  *exp = *expNew;
1237                                  delete expNew;
1238                               }
1239                               else
1240                                  exp.type = unknownErrorExp;
1241                            }
1242                            else
1243                            {
1244                               // TESTING THIS HERE...
1245                               exp.type = constantExp;
1246                               exp.constant = PrintHexUInt64(address);
1247
1248                               exp.address = address;
1249                               exp.hasAddress = true;
1250                               exp.isConstant = true;
1251                            }
1252                         }
1253                      }
1254                      //else
1255                      //   exp.type = ExpUnknownError;
1256
1257                      //FreeExpContents(exp);
1258                      //exp.constant = PrintUInt64(value);
1259                      //exp.type = constantExp;
1260                   }
1261                }
1262                else
1263                {
1264                   if(type && (type.kind == structType || type.kind == unionType))
1265                   {
1266                      uint offset = 0;
1267                      Type memberType = exp.member.member ? FindMemberAndOffset(type, exp.member.member.string, &offset) : null;
1268                      if(memberType)
1269                      {
1270                         char * evaluation = null;
1271                         ExpressionType evalError = dummyExp;
1272                         uint64 address;
1273                         Expression prev = exp.prev, next = exp.next;
1274                         char format;
1275                         int size = memberType.size;
1276                         Expression expNew;
1277                         Type dataType = memberType;
1278                         TypeKind kind = dummyType;
1279
1280                         if(dataType.kind == classType && dataType._class.registered &&
1281                               (dataType._class.registered.type == enumClass || dataType._class.registered.type == bitClass || dataType._class.registered.type == unitClass))
1282                            dataType = dataType._class.registered.dataType;
1283
1284                         format = GetGdbFormatChar(dataType);
1285
1286                         if(memberExp.hasAddress)
1287                            address = memberExp.address;
1288                         else if(memberExp.type == constantExp)
1289                            GetUInt64(memberExp, &address);
1290
1291                         address += offset;
1292
1293                         if((dataType.kind == classType && dataType._class &&
1294                               (!dataType._class.registered || dataType._class.registered.type == normalClass || dataType._class.registered.type == noHeadClass || dataType._class.registered.type == systemClass)) ||
1295                            (dataType.kind != classType && dataType.kind != arrayType && dataType.kind != structType && dataType.kind != unionType))
1296                         {
1297                            evaluation = Debugger::ReadMemory(address, size, format, &evalError);
1298                            if(evalError != dummyExp)
1299                            {
1300                               exp.type = evalError;
1301                               exp.constant = PrintHexUInt64(address);
1302                            }
1303                            else if(evaluation)
1304                            {
1305                               expNew = ParseExpressionString(evaluation);
1306                               delete evaluation;
1307                               expNew.destType = exp.expType;
1308                               if(exp.expType)
1309                                  exp.expType.refCount++;
1310                               //FreeType(memberExp.destType);
1311                               FreeType(exp.expType);
1312                               FreeType(exp.destType);
1313                               FreeExpContents(exp);
1314                               ProcessExpressionType(expNew);
1315                               DebugComputeExpression(expNew);
1316                               expNew.prev = prev;
1317                               expNew.next = next;
1318                               expNew.isConstant = true;
1319                               expNew.address = address;
1320                               expNew.hasAddress = true;
1321                               *exp = *expNew;
1322                               delete expNew;
1323                            }
1324                            else
1325                               exp.type = unknownErrorExp;
1326                         }
1327                         else
1328                         {
1329                            FreeExpContents(exp);
1330
1331                            // TESTING THIS HERE...
1332                            exp.type = constantExp;
1333                            exp.constant = PrintHexUInt64(address);
1334
1335                            exp.address = address;
1336                            exp.hasAddress = true;
1337                            exp.isConstant = true;
1338                         }
1339                      }
1340                      else
1341                         exp.type = memberSymbolErrorExp;
1342                   }
1343                   else
1344                      exp.type = memberSymbolErrorExp;
1345                }
1346             }
1347
1348             //if(exp.type != memberExp)
1349             {
1350                //FreeExpression(memberExp);
1351                //FreeIdentifier(memberID);
1352             }
1353          }
1354          else
1355          {
1356             exp.type = memberSymbolErrorExp;
1357          }
1358          break;
1359       }
1360       case typeSizeExp:
1361       {
1362          Type type = ProcessType(exp.typeName.qualifiers, exp.typeName.declarator);
1363          FreeExpContents(exp);
1364          exp.constant = PrintUInt(ComputeTypeSize(type));
1365          exp.type = constantExp;
1366          FreeType(type);
1367          break;
1368       }
1369       case classSizeExp:
1370       {
1371          Symbol classSym = FindClass(exp._class.name);
1372          if(classSym && classSym.registered)
1373          {
1374             //exp.constant = PrintUInt(classSym.registered.size);
1375             //exp.type = constantExp;
1376
1377             char className[1024];
1378             sprintf(className, "__ecereClass_%s", classSym.string);
1379             FreeExpContents(exp);
1380             exp.type = pointerExp;
1381             exp.member.exp = MkExpIdentifier(MkIdentifier(className));
1382             exp.member.member = MkIdentifier("size");
1383          }
1384          break;
1385       }
1386       case castExp:
1387       {
1388          DebugComputeExpression(exp.cast.exp);
1389
1390          if(ExpressionIsError(exp.cast.exp)) //.type == ExpSymbolError
1391             CarryExpressionError(exp, exp.cast.exp);
1392          else
1393          {
1394             exp.hasAddress = exp.cast.exp.hasAddress;
1395             exp.address = exp.cast.exp.address;
1396             if(exp.cast.exp.type == constantExp && exp.expType)
1397             {
1398                Type type = exp.expType;
1399                if(type.kind == classType && type._class && type._class.registered)
1400                {
1401                   Class _class = type._class.registered;
1402                   if(_class.type == unitClass || _class.type == bitClass || _class.type == enumClass)
1403                   {
1404                      if(!_class.dataType)
1405                         _class.dataType = ProcessTypeString(_class.dataTypeString, false);
1406                      type = _class.dataType;
1407                   }
1408                }
1409
1410                switch(type.kind)
1411                {
1412                   case charType:
1413                      if(type.isSigned)
1414                      {
1415                         char value;
1416                         GetChar(exp.cast.exp, &value);
1417                         FreeExpContents(exp);
1418                         exp.constant = PrintChar(value);
1419                         exp.type = constantExp;
1420                         exp.isConstant = true;
1421                      }
1422                      else
1423                      {
1424                         unsigned char value;
1425                         GetUChar(exp.cast.exp, &value);
1426                         FreeExpContents(exp);
1427                         exp.constant = PrintUChar(value);
1428                         exp.type = constantExp;
1429                         exp.isConstant = true;
1430                      }
1431                      break;
1432                   case shortType:
1433                      if(type.isSigned)
1434                      {
1435                         short value;
1436                         GetShort(exp.cast.exp, &value);
1437                         FreeExpContents(exp);
1438                         exp.constant = PrintShort(value);
1439                         exp.type = constantExp;
1440                         exp.isConstant = true;
1441                      }
1442                      else
1443                      {
1444                         unsigned short value;
1445                         GetUShort(exp.cast.exp, &value);
1446                         FreeExpContents(exp);
1447                         exp.constant = PrintUShort(value);
1448                         exp.type = constantExp;
1449                         exp.isConstant = true;
1450                      }
1451                      break;
1452                   case intType:
1453                      if(type.isSigned)
1454                      {
1455                         int value;
1456                         GetInt(exp.cast.exp, &value);
1457                         FreeExpContents(exp);
1458                         exp.constant = PrintInt(value);
1459                         exp.type = constantExp;
1460                         exp.isConstant = true;
1461                      }
1462                      else
1463                      {
1464                         unsigned int value;
1465                         GetUInt(exp.cast.exp, &value);
1466                         FreeExpContents(exp);
1467                         exp.constant = PrintUInt(value);
1468                         exp.type = constantExp;
1469                         exp.isConstant = true;
1470                      }
1471                      break;
1472                   case int64Type:
1473                      if(type.isSigned)
1474                      {
1475                         int64 value;
1476                         GetInt64(exp.cast.exp, &value);
1477                         FreeExpContents(exp);
1478                         exp.constant = PrintInt64(value);
1479                         exp.type = constantExp;
1480                         exp.isConstant = true;
1481                      }
1482                      else
1483                      {
1484                         uint64 value;
1485                         GetUInt64(exp.cast.exp, &value);
1486                         FreeExpContents(exp);
1487                         exp.constant = PrintUInt64(value);
1488                         exp.type = constantExp;
1489                         exp.isConstant = true;
1490                      }
1491                      break;
1492                   case pointerType:
1493                   case classType:
1494                   {
1495                      uint64 value;
1496                      GetUInt64(exp.cast.exp, &value);
1497                      FreeExpContents(exp);
1498                      if(type.kind == pointerType || type.kind == classType)
1499                         exp.constant = PrintHexUInt64(value);
1500                      else
1501                         exp.constant = PrintUInt64(value);
1502                      exp.type = constantExp;
1503                      exp.isConstant = true;
1504                      break;
1505                   }
1506                   case floatType:
1507                   {
1508                      float value;
1509                      GetFloat(exp.cast.exp, &value);
1510                      FreeExpContents(exp);
1511                      exp.constant = PrintFloat(value);
1512                      exp.type = constantExp;
1513                      exp.isConstant = true;
1514                      break;
1515                   }
1516                   case doubleType:
1517                   {
1518                      double value;
1519                      GetDouble(exp.cast.exp, &value);
1520                      FreeExpContents(exp);
1521                      exp.constant = PrintDouble(value);
1522                      exp.type = constantExp;
1523                      exp.isConstant = true;
1524                      break;
1525                   }
1526                }
1527             }
1528          }
1529          break;
1530       }
1531       case conditionExp:
1532       {
1533          if(exp.cond.cond)
1534          {
1535             DebugComputeExpression(exp.cond.cond);
1536
1537             if(ExpressionIsError(exp.cond.cond))
1538                CarryExpressionError(exp, exp.cond.cond);
1539             else if(exp.cond.cond.type == constantExp && exp.cond.cond.constant)
1540             {
1541                Expression e = null;
1542                if(strtol(exp.cond.cond.constant, null, 0))
1543                {
1544                   for(e = exp.cond.exp ? exp.cond.exp->first : null; e; e = e.next)
1545                   {
1546                      DebugComputeExpression(e);
1547                      if(!e.next) break;
1548                   }
1549                   if(e)
1550                   {
1551                      if(ExpressionIsError(e))
1552                      {
1553                         CarryExpressionError(exp, e);
1554                         e = null;
1555                      }
1556                      else
1557                         exp.cond.exp->Remove(e);
1558                   }
1559                }
1560                else
1561                {
1562                   e = exp.cond.elseExp;
1563                   if(e)
1564                   {
1565                      DebugComputeExpression(e);
1566                      if(ExpressionIsError(e))
1567                      {
1568                         CarryExpressionError(exp, e);
1569                         e = null;
1570                      }
1571                      else
1572                         exp.cond.elseExp = null;
1573                   }
1574                }
1575                if(e)
1576                {
1577                   FreeType(exp.expType);
1578                   FreeType(exp.destType);
1579                   e.prev = exp.prev;
1580                   e.next = exp.next;
1581                   FreeExpContents(exp);
1582                   *exp = *e;
1583                   delete e;
1584                }
1585                else if(!ExpressionIsError(exp))
1586                {
1587                   FreeExpContents(exp);
1588                   exp.type = unknownErrorExp;
1589                }
1590             }
1591             else
1592             {
1593                FreeExpContents(exp);
1594                exp.type = unknownErrorExp;
1595             }
1596          }
1597          else
1598          {
1599             FreeExpContents(exp);
1600             exp.type = unknownErrorExp;
1601          }
1602          break;
1603       }
1604    }
1605 }