ide;debugger; (#1030) fix new memory leaks.
[sdk] / ide / src / debugger / Debugger.ec
index b702a96..c5228f8 100644 (file)
@@ -170,55 +170,26 @@ public char * StripQuotes2(char * string, char * output)
 // String Escape Copy
 static void strescpy(char * d, char * s)
 {
-   int j, k;
-   j = k = 0;
-   while(s[j])
+   int j = 0, k = 0;
+   char ch;
+   while((ch = s[j]))
    {
-      switch(s[j])
+      switch(ch)
       {
-         case '\n':
-            d[k] = '\\';
-            d[++k] = 'n';
-            break;
-         case '\t':
-            d[k] = '\\';
-            d[++k] = 't';
-            break;
-         case '\a':
-            d[k] = '\\';
-            d[++k] = 'a';
-            break;
-         case '\b':
-            d[k] = '\\';
-            d[++k] = 'b';
-            break;
-         case '\f':
-            d[k] = '\\';
-            d[++k] = 'f';
-            break;
-         case '\r':
-            d[k] = '\\';
-            d[++k] = 'r';
-            break;
-         case '\v':
-            d[k] = '\\';
-            d[++k] = 'v';
-            break;
-         case '\\':
-            d[k] = '\\';
-            d[++k] = '\\';
-            break;
-         case '\"':
-            d[k] = '\\';
-            d[++k] = '\"';
-            break;
-         default:
-            d[k] = s[j];
+         case '\n': d[k] = '\\'; d[++k] = 'n'; break;
+         case '\t': d[k] = '\\'; d[++k] = 't'; break;
+         case '\a': d[k] = '\\'; d[++k] = 'a'; break;
+         case '\b': d[k] = '\\'; d[++k] = 'b'; break;
+         case '\f': d[k] = '\\'; d[++k] = 'f'; break;
+         case '\r': d[k] = '\\'; d[++k] = 'r'; break;
+         case '\v': d[k] = '\\'; d[++k] = 'v'; break;
+         case '\\': d[k] = '\\'; d[++k] = '\\'; break;
+         case '\"': d[k] = '\\'; d[++k] = '\"'; break;
+         default: d[k] = s[j];
       }
-      ++j;
-      ++k;
+      j++, k++;
    }
-   d[k] = s[j];
+   d[k] = '\0';
 }
 
 static char * CopyUnescapedSystemPath(char * p)
@@ -255,54 +226,33 @@ static char * CopyUnescapedString(char * s)
 
 static void struscpy(char * d, char * s)
 {
-   int j, k;
-   j = k = 0;
-   while(s[j])
+   int j = 0, k = 0;
+   char ch;
+   while((ch = s[j]))
    {
-      switch(s[j])
+      switch(ch)
       {
          case '\\':
             switch(s[++j])
             {
-               case 'n':
-                  d[k] = '\n';
-                  break;
-               case 't':
-                  d[k] = '\t';
-                  break;
-               case 'a':
-                  d[k] = '\a';
-                  break;
-               case 'b':
-                  d[k] = '\b';
-                  break;
-               case 'f':
-                  d[k] = '\f';
-                  break;
-               case 'r':
-                  d[k] = '\r';
-                  break;
-               case 'v':
-                  d[k] = '\v';
-                  break;
-               case '\\':
-                  d[k] = '\\';
-                  break;
-               case '\"':
-                  d[k] = '\"';
-                  break;
-               default:
-                  d[k] = '\\';
-                  d[++k] = s[j];
+               case 'n': d[k] = '\n'; break;
+               case 't': d[k] = '\t'; break;
+               case 'a': d[k] = '\a'; break;
+               case 'b': d[k] = '\b'; break;
+               case 'f': d[k] = '\f'; break;
+               case 'r': d[k] = '\r'; break;
+               case 'v': d[k] = '\v'; break;
+               case '\\': d[k] = '\\'; break;
+               case '\"': d[k] = '\"'; break;
+               default: d[k] = '\\'; d[++k] = s[j];
             }
             break;
          default:
             d[k] = s[j];
       }
-      ++j;
-      ++k;
+      j++, k++;
    }
-   d[k] = s[j];
+   d[k] = '\0';
 }
 
 static char * StripBrackets(char * string)
@@ -349,10 +299,10 @@ static int StringGetInt(char * string, int start)
 static int TokenizeList(char * string, const char seperator, Array<char *> tokens)
 {
    uint level = 0;
-   
+
    bool quoted = false, escaped = false;
    char * start = string, ch;
-   
+
    for(; (ch = *string); string++)
    {
       if(!start)
@@ -397,11 +347,9 @@ static bool TokenizeListItem(char * string, DebugListItem item)
       *equal = '\0';
       equal++;
       item.value = equal;
-      equal = null;
       return true;
    }
-   else
-      return false;
+   return false;
 }
 
 static bool CheckCommandAvailable(const char * command)
@@ -430,6 +378,7 @@ static bool CheckCommandAvailable(const char * command)
                if(fl.stats.attribs.isFile && !fstrcmp(fl.name, name))
                {
                   available = true;
+                  fl.Stop();
                   break;
                }
             }
@@ -523,7 +472,7 @@ class Debugger
 
    char * targetDir;
    char * targetFile;
-   
+
    GdbExecution gdbExecution;
    DebuggerUserAction userAction;
    DebuggerState state;
@@ -535,7 +484,7 @@ class Debugger
    GdbDataStop stopItem;
    GdbDataBreakpoint bpItem;
    Frame activeFrame;
-   
+
    List<Breakpoint> sysBPs { };
    Breakpoint bpRunToCursor;
    Breakpoint intBpEntry;
@@ -607,6 +556,7 @@ class Debugger
                   if(bp)
                      _dpl2(_dpct, dplchan::debuggerBreakpoints, 0, "gdb stopped by a breakpoint: ", bp.type, "(", s=bp.CopyLocationString(false), ")"); delete s;
                }
+               delete bpReport;
             }
 #endif
          }
@@ -841,15 +791,15 @@ class Debugger
 
       targetDir = null;
       targetFile = null;
-      
+
       _ChangeState(none);
       event = none;
       breakType = none;
 
-      stopItem = null;
-      bpItem = null;
+      delete stopItem;
+      delete bpItem;
       activeFrame = 0;
-      
+
       bpRunToCursor = null;
 
       delete currentCompiler;
@@ -863,7 +813,7 @@ class Debugger
       /*GdbThread gdbThread
       Timer gdbTimer*/
    }
-   
+
    Debugger()
    {
       _dpl2(_dpct, dplchan::debuggerCall, 0, "Debugger::constructor");
@@ -1063,7 +1013,7 @@ class Debugger
    {
       bool returnedExitCode = false;
       char verboseExitCode[128];
-      
+
       _dpl2(_dpct, dplchan::debuggerCall, 0, "Debugger::HandleExit(", reason, ", ", code, ")");
       _ChangeState(loaded); // this state change seems to be superfluous, might be in case of gdb crash
       targetProcessId = 0;
@@ -1075,7 +1025,7 @@ class Debugger
       }
       else
          verboseExitCode[0] = '\0';
-      
+
       event = exit;
 
       // ClearBreakDisplay();
@@ -1122,7 +1072,7 @@ class Debugger
       }
       ide.Update(null);
    }
-      
+
    DebuggerState StartSession(CompilerConfig compiler, ProjectConfig config, int bitDepth, bool useValgrind, bool restart, bool ignoreBreakpoints)
    {
       DebuggerState result = none;
@@ -1323,7 +1273,7 @@ class Debugger
             *lineTopFrame = stopItem.frame.line;
          else
             *lineTopFrame = 0;
-         
+
          if(*lineTopFrame == *lineCursor && *lineTopFrame)
             *lineTopFrame = 0;
       }
@@ -1387,7 +1337,7 @@ class Debugger
             }
          }
       }
-      
+
       // moving code cursors is futile, on next step, stop, hit, cursors will be offset anyways
    }
 
@@ -1405,9 +1355,9 @@ class Debugger
       while(debuggerFileDialog.Modal())
       {
          strcpy(sourceDir, debuggerFileDialog.filePath);
-         if(!fstrcmp(ide.workspace.projectDir, sourceDir) && 
-                  MessageBox { type = yesNo, master = ide, 
-                              contents = $"This is the project directory.\nWould you like to try again?", 
+         if(!fstrcmp(ide.workspace.projectDir, sourceDir) &&
+                  MessageBox { type = yesNo, master = ide,
+                              contents = $"This is the project directory.\nWould you like to try again?",
                               text = $"Invalid Source Directory" }.Modal() == no)
             return false;
          else
@@ -1420,10 +1370,10 @@ class Debugger
                   break;
                }
             }
-            
-            if(srcDir && 
-                  MessageBox { type = yesNo, master = ide, 
-                              contents = $"This source directory is already specified.\nWould you like to try again?", 
+
+            if(srcDir &&
+                  MessageBox { type = yesNo, master = ide,
+                              contents = $"This source directory is already specified.\nWould you like to try again?",
                               text = $"Invalid Source Directory" }.Modal() == no)
                return false;
             else
@@ -1434,15 +1384,15 @@ class Debugger
                   strcpy(file, sourceDir);
                   PathCat(file, test);
                   result = FileExists(file);
-                  if(!result && 
-                        MessageBox { type = yesNo, master = ide, 
-                                    contents = $"Unable to locate source file.\nWould you like to try again?", 
+                  if(!result &&
+                        MessageBox { type = yesNo, master = ide,
+                                    contents = $"Unable to locate source file.\nWould you like to try again?",
                                     text = $"Invalid Source Directory" }.Modal() == no)
                         return false;
                }
                else
                   result = true;
-               
+
                if(result)
                   return true;
             }
@@ -1456,7 +1406,7 @@ class Debugger
       _dpl2(_dpct, dplchan::debuggerCall, 0, "Debugger::AddSourceDir(", sourceDir, ")");
       ide.workspace.sourceDirs.Add(CopyString(sourceDir));
       ide.workspace.Save();
-      
+
       if(targeted)
       {
          DebuggerState oldState = state;
@@ -1527,7 +1477,7 @@ class Debugger
                }
                if(srcDir)
                   break;
-               
+
                if(SourceDirDialog(title, directory, null, sourceDir))
                {
                   if(IsPathInsideOf(absolutePath, sourceDir))
@@ -1536,8 +1486,8 @@ class Debugger
                      MakePathRelative(absolutePath, sourceDir, relativePath);
                      break;
                   }
-                  else if(MessageBox { type = yesNo, master = ide, 
-                                 contents = $"You must provide a valid source directory in order to place a breakpoint in this file.\nWould you like to try again?", 
+                  else if(MessageBox { type = yesNo, master = ide,
+                                 contents = $"You must provide a valid source directory in order to place a breakpoint in this file.\nWould you like to try again?",
                                  text = $"Invalid Source Directory" }.Modal() == no)
                      return;
                }
@@ -1604,7 +1554,7 @@ class Debugger
       Array<char *> argumentTokens { minAllocSize = 50 };
       DebugListItem item { };
       Argument arg;
-      
+
       //_dpl2(_dpct, dplchan::debuggerCall, 0, "Debugger::ParseFrame()");
       TokenizeList(string, ',', frameTokens);
       for(i = 0; i < frameTokens.count; i++)
@@ -1682,7 +1632,7 @@ class Debugger
          else
             _dpl(0, "Bad frame");
       }
-      
+
       delete frameTokens;
       delete argsTokens;
       delete argumentTokens;
@@ -1777,6 +1727,8 @@ class Debugger
                _dpl2(_dpct, dplchan::gdbProtoUnknown, 0, "breakpoint member (", item.name, "=", item.value, ") is unheard of");
          }
       }
+      delete bpTokens;
+      delete item;
       return bp;
    }
 
@@ -1808,7 +1760,7 @@ class Debugger
          vsnprintf(string, sizeof(string), format, args);
          string[sizeof(string)-1] = 0;
          va_end(args);
-         
+
          gdbReady = false;
          ide.debugger.serialSemaphore.TryWait();
 
@@ -1832,7 +1784,7 @@ class Debugger
          app.Unlock();
          ide.debugger.serialSemaphore.Wait();
          app.Lock();
-      } 
+      }
    }
 
    bool ValidateBreakpoint(Breakpoint bp)
@@ -1979,6 +1931,7 @@ class Debugger
                   if(bp.bp)
                      _dpl(0, "problem");
 #endif
+                  delete bp.bp;
                   bp.bp = GdbDataBreakpoint { };
                }
             }
@@ -1993,6 +1946,7 @@ class Debugger
       {
          GdbCommand(false, "-break-delete %s", bp.bp.number);
          bp.inserted = false;
+         delete bp.bp;
          bp.bp = { };
       }
    }
@@ -2055,6 +2009,7 @@ class Debugger
                bpItem.multipleBPs.Free();
                delete bpItem.multipleBPs;
             }
+            delete bp.bp;
             bp.bp = bpItem;
             bpItem = null;
             bp.inserted = (bp.bp && bp.bp.number && strcmp(bp.bp.number, "0"));
@@ -2357,7 +2312,7 @@ class Debugger
       }
       else
          ChangeWorkingDir(ide.workspace.projectDir);
-      
+
       ide.SetPath(true, compiler, config, bitDepth);
 
       // TODO: This pollutes the environment, but at least it works
@@ -2551,6 +2506,21 @@ class Debugger
             gdbThread.Wait();
             app.Lock();
          }
+         if(vgLogThread)
+         {
+            app.Unlock();
+            vgLogThread.Wait();
+            app.Lock();
+         }
+         if(vgTargetThread)
+         {
+            app.Unlock();
+            vgTargetThread.Wait();
+            app.Lock();
+         }
+
+         if(vgLogFile)
+            delete vgLogFile;
          if(gdbHandle)
          {
             gdbHandle.Wait();
@@ -2571,7 +2541,7 @@ class Debugger
          bp.Reset();
       if(bpRunToCursor)
          bpRunToCursor.Reset();
-      
+
       ide.outputView.debugBox.Logf($"Debugging stopped\n");
       ClearBreakDisplay();
       ide.Update(null);
@@ -2587,7 +2557,7 @@ class Debugger
             progThread.Wait();
             app.Lock();
             delete fifoFile;
-         }         
+         }
          DeleteFile(progFifoPath);
          progFifoPath[0] = '\0';
          rmdir(progFifoDir);
@@ -2629,12 +2599,12 @@ class Debugger
    bool ResolveWatch(Watch wh)
    {
       bool result = false;
-      
+
       _dpl2(_dpct, dplchan::debuggerWatches, 0, "Debugger::ResolveWatch()");
       wh.Reset();
 
       /*delete wh.value;
-      if(wh.type) 
+      if(wh.type)
       {
          FreeType(wh.type);
          wh.type = null;
@@ -2665,9 +2635,9 @@ class Debugger
                SetGlobalContext(codeEditor.globalContext);
                SetGlobalData(&codeEditor.globalData);
             }
-         
+
             exp = ParseExpressionString(wh.expression);
-            
+
             if(exp && !parseError)
             {
                char expString[4096];
@@ -2728,7 +2698,7 @@ class Debugger
                            long v = (long)exp.val.f;
                            sprintf(temp, "%i", v);
                            break;
-                        } 
+                        }
                         case doubleType:
                         {
                            long v = (long)exp.val.d;
@@ -2765,7 +2735,7 @@ class Debugger
                            long v = (long)exp.val.f;
                            sprintf(temp, "0x%x", v);
                            break;
-                        } 
+                        }
                         case doubleType:
                         {
                            long v = (long)exp.val.d;
@@ -2802,7 +2772,7 @@ class Debugger
                            long v = (long)exp.val.f;
                            sprintf(temp, "0o%o", v);
                            break;
-                        } 
+                        }
                         case doubleType:
                         {
                            long v = (long)exp.val.d;
@@ -2877,9 +2847,9 @@ class Debugger
                   case constantExp:
                   case stringExp:
                      // Temporary Code for displaying Strings
-                     if((exp.expType && ((exp.expType.kind == pointerType || 
-                              exp.expType.kind == arrayType) && exp.expType.type.kind == charType)) || 
-                           (wh.type && wh.type.kind == classType && wh.type._class && 
+                     if((exp.expType && ((exp.expType.kind == pointerType ||
+                              exp.expType.kind == arrayType) && exp.expType.type.kind == charType)) ||
+                           (wh.type && wh.type.kind == classType && wh.type._class &&
                               wh.type._class.registered && wh.type._class.registered.type == normalClass &&
                               !strcmp(wh.type._class.registered.name, "String")))
                      {
@@ -2909,7 +2879,7 @@ class Debugger
                            else
                               snprintf(value, sizeof(value), (GetRuntimePlatform() == win32) ? "0x%08I64x " : "0x%08llx ", address);
                            value[sizeof(value)-1] = 0;
-                           
+
                            if(!address)
                               strcat(value, $"Null string");
                            else
@@ -2929,12 +2899,12 @@ class Debugger
                                  {
                                     int c;
                                     char ch;
-                                    
+
                                     for(c = 0; (ch = string[c]) && c<4096; c++)
-                                       value[len++] = ch;                                 
+                                       value[len++] = ch;
                                     value[len++] = ')';
                                     value[len++] = '\0';
-                                    
+
                                  }
                                  else
                                  {
@@ -2955,7 +2925,7 @@ class Debugger
                            wh.value = CopyString(value);
                         }
                      }
-                     else if(wh.type && wh.type.kind == classType && wh.type._class && 
+                     else if(wh.type && wh.type.kind == classType && wh.type._class &&
                               wh.type._class.registered && wh.type._class.registered.type == enumClass)
                      {
                         uint64 value = strtoul(exp.constant, null, 0);
@@ -2971,7 +2941,7 @@ class Debugger
                            wh.value = CopyString($"Invalid Enum Value");
                         result = true;
                      }
-                     else if(wh.type && (wh.type.kind == charType || (wh.type.kind == classType && wh.type._class && 
+                     else if(wh.type && (wh.type.kind == charType || (wh.type.kind == classType && wh.type._class &&
                               wh.type._class.registered && !strcmp(wh.type._class.registered.fullName, "ecere::com::unichar"))) )
                      {
                         unichar value;
@@ -3037,7 +3007,7 @@ class Debugger
                         else
                            snprintf(string, sizeof(string), "\'%s\' (%d)", charString, value);
                         string[sizeof(string)-1] = 0;
-                        
+
                         wh.value = CopyString(string);
                         result = true;
                      }
@@ -3059,7 +3029,7 @@ class Debugger
                         if(exp.member.memberType == propertyMember)
                            snprintf(watchmsg, sizeof(watchmsg), $"Missing property evaluation support for \"%s\"", wh.expression);
                         else
-                           snprintf(watchmsg, sizeof(watchmsg), $"Evaluation failed for \"%s\" of type \"%s\"", wh.expression, 
+                           snprintf(watchmsg, sizeof(watchmsg), $"Evaluation failed for \"%s\" of type \"%s\"", wh.expression,
                                  exp.type.OnGetString(tempString, null, null));
                      }
                      break;
@@ -3069,16 +3039,16 @@ class Debugger
                snprintf(watchmsg, sizeof(watchmsg), $"Invalid expression: \"%s\"", wh.expression);
             if(exp) FreeExpression(exp);
 
-            
+
             SetPrivateModule(backupPrivateModule);
             SetCurrentContext(backupContext);
             SetTopContext(backupContext);
             SetGlobalContext(backupContext);
             SetThisClass(backupThisClass);
          }
-         //else 
+         //else
          //   wh.value = CopyString("No source file found for selected frame");
-         
+
          watchmsg[sizeof(watchmsg)-1] = 0;
          if(!wh.value)
             wh.value = CopyString(watchmsg);
@@ -3267,7 +3237,7 @@ class Debugger
             gdbTimer.Stop();
             gdbHandle.Wait();
             delete gdbHandle;
-            
+
             ide.outputView.debugBox.Logf($"Debugger Fatal Error: GDB lost\n");
             ide.outputView.debugBox.Logf($"Debugging stopped\n");
             ide.Update(null);
@@ -3286,7 +3256,7 @@ class Debugger
       DebugListItem item { };
       DebugListItem item2 { };
       bool setWaitingForPID = false;
-      
+
 #if defined(GDB_DEBUG_CONSOLE) || defined(GDB_DEBUG_GUI)
 #ifdef GDB_DEBUG_CONSOLE
       // _dpl2(_dpct, dplchan::gdbOutput, 0, output);
@@ -3323,7 +3293,7 @@ class Debugger
          if(ide.gdbDialog) ide.gdbDialog.AddOutput(output);
 #endif
 #endif
-      
+
       switch(output[0])
       {
          case '~':
@@ -3400,6 +3370,7 @@ class Debugger
                      if(bpItem)
                         _dpl(0, "problem");
 #endif
+                     delete bpItem;
                      bpItem = ParseBreakpoint(item.value, outTokens);
                      //breakType = bpValidation;
                   }
@@ -3963,6 +3934,7 @@ class Debugger
             DirExpression targetDirExp = prj.GetTargetDir(currentCompiler, prj.config, bitDepth);
             strcpy(prjTargetPath, prj.topNode.path);
             PathCat(prjTargetPath, targetDirExp.dir);
+            delete targetDirExp;
             prjTargetFile[0] = '\0';
             prj.CatTargetFileName(prjTargetFile, currentCompiler, prj.config);
             PathCat(prjTargetPath, prjTargetFile);
@@ -4572,6 +4544,8 @@ class GdbDataBreakpoint : struct
       delete at;
       if(multipleBPs) multipleBPs.Free();
       delete multipleBPs;
+      delete number;
+      delete fullname;
    }
 
    ~GdbDataBreakpoint()
@@ -4756,7 +4730,7 @@ class Breakpoint : struct
 class Watch : struct
 {
    class_no_expansion;
-   
+
    Type type;
    char * expression;
    char * value;