ide, debugger; fixed breakpoints issues when using run to cursor together with breakp...
[sdk] / ide / src / debugger / Debugger.ec
index 6457ee1..0e9e984 100644 (file)
@@ -3,11 +3,14 @@ import "process"
 import "debugFindCtx"
 import "debugTools"
 
-//#define GDB_DEBUG_CONSOLE
+#ifdef _DEBUG
+#define GDB_DEBUG_CONSOLE
+#endif
 
-extern char * strrchr(char * s, char c);
+extern char * strrchr(const char * s, int c);
 
 #define uint _uint
+#define strlen _strlen
 #include <stdarg.h>
 #include <unistd.h>
 
@@ -20,32 +23,7 @@ extern char * strrchr(char * s, char c);
 #include <sys/time.h> // Required on Apple...
 #endif
 #undef uint
-
-//bool eString_PathInsidePath(char * to, char * path)
-bool eString_PathInsideOf(char * path, char * of)
-{
-   if(!path[0] || !of[0])
-      return false;  // What to do here? Ever used?
-   else
-   {
-      char ofPart[MAX_FILENAME], ofRest[MAX_LOCATION];
-      char pathPart[MAX_FILENAME], pathRest[MAX_LOCATION];
-      strcpy(ofRest, of);
-      strcpy(pathRest, path);
-      for(; ofRest[0] && pathRest[0];)
-      {
-         SplitDirectory(ofRest, ofPart, ofRest);      
-         SplitDirectory(pathRest, pathPart, pathRest);
-         if(fstrcmp(pathPart, ofPart))
-            return false;
-      }
-      if(!ofRest[0] && !pathRest[0])  // paths are identical - should return false or true? (changed to false)
-         return false;
-      else if(!pathRest[0])           // not inside of, it's the other way around
-         return false;
-      return true;
-   }
-}
+#undef strlen
 
 public char * StripQuotes2(char * string, char * output)
 {
@@ -60,8 +38,7 @@ public char * StripQuotes2(char * string, char * output)
          if(escaped || ch != '\"')
          {
             output[d++] = ch;
-            if(ch == '\\')
-               escaped ^= true;
+            escaped = !escaped && ch == '\\';
          }
          else
             quoted = false;
@@ -258,25 +235,28 @@ static int TokenizeList(char * string, const char seperator, Array<char *> token
 {
    uint level = 0;
    
-   bool quoted = false; //bool escaped = false;
-   char * start = string;
+   bool quoted = false, escaped = false;
+   char * start = string, ch;
    
-   for(; *string; string++)
+   for(; (ch = *string); string++)
    {
       if(!start)
          start = string;
+
       if(quoted)
       {
-         if(*string == '\"')
+         if(escaped || ch != '\"')
+            escaped = !escaped && ch == '\\';
+         else
             quoted = false;
       }
-      else if(*string == '\"')
+      else if(ch == '\"')
          quoted = true;
-      else if(*string == '{' || *string == '[' || *string == '(' || *string == '<')
+      else if(ch == '{' || ch == '[' || ch == '(' || ch == '<')
          level++;
-      else if(*string == '}' || *string == ']' || *string == ')' || *string == '>')
+      else if(ch == '}' || ch == ']' || ch == ')' || ch == '>')
          level--;
-      else if(*string == seperator && !level)
+      else if(ch == seperator && !level)
       {
          tokens.Add(start);
          *string = '\0';
@@ -326,7 +306,7 @@ char progFifoDir[MAX_LOCATION];
 enum DebuggerState { none, prompt, loaded, running, stopped, terminated };
 enum DebuggerEvent { none, hit, breakEvent, signal, stepEnd, functionEnd, exit };
 enum DebuggerAction { none, internal, restart, stop, selectFrame }; //, bpValidation
-enum BreakpointType { none, internalMain, internalWinMain, internalModulesLoaded, user, runToCursor };
+enum BreakpointType { none, internalMain, internalWinMain, internalModulesLoaded, user, runToCursor, internalModuleLoad };
 enum DebuggerEvaluationError { none, symbolNotFound, memoryCantBeRead, unknown };
 
 FileDialog debuggerFileDialog { type = selectDir };
@@ -337,6 +317,7 @@ static DebugEvaluationData eval { };
 static int targetProcessId;
 
 static bool gdbReady;
+static bool breakpointError;
 
 class Debugger
 {
@@ -383,6 +364,7 @@ class Debugger
 
    CompilerConfig currentCompiler;
    ProjectConfig prjConfig;
+   int bitDepth;
 
    CodeEditor codeEditor;
 
@@ -411,12 +393,11 @@ class Debugger
 #endif
             }
          }
-
          switch(breakType)
          {
             case restart:
                breakType = none;
-               Restart(currentCompiler, prjConfig);
+               Restart(currentCompiler, prjConfig, bitDepth);
                break;
             case stop:
                breakType = none;
@@ -464,10 +445,21 @@ class Debugger
                         break;
                      }
                   }
+                  if(bp && bp.type != user && stopItem && stopItem.frame)
+                  {
+                     // In case the user put a breakpoint where an internal breakpoint is, avoid the confusion...
+                     for(i : ide.workspace.breakpoints)
+                     {
+                        if(i.bp && i.line == stopItem.frame.line && !fstrcmp(i.absoluteFilePath, stopItem.frame.absoluteFile))
+                           bp = i;
+                        break;
+                     }
+                  }
                   bpHit = bp;
                   
                   if(!(!userBreakOnInternBreak && 
-                        bp && (bp.type == internalMain || bp.type == internalWinMain || bp.type == internalModulesLoaded)))
+                        bp && (bp.type == internalMain || bp.type == internalWinMain ||
+                        bp.type == internalModulesLoaded || bp.type == internalModuleLoad)))
                      monitor = true;
                   hitThread = stopItem.threadid;
                }
@@ -511,7 +503,7 @@ class Debugger
                // Why was SelectFrame missing here?
                SelectFrame(activeFrameLevel);
                GoToStackFrameLine(activeFrameLevel, curEvent == signal || curEvent == stepEnd /*false*/);
-               ide.Activate();
+               ideMainFrame.Activate();   // TOFIX: ide.Activate() is not reliable (app inactive)
                ide.Update(null);
                if(curEvent == signal)
                   ide.outputView.Show();
@@ -530,7 +522,7 @@ class Debugger
                break;
          }
          
-         if(curEvent == DebuggerEvent::breakEvent || curEvent == stepEnd || curEvent == functionEnd)
+         if(curEvent != hit)
             ignoreBreakpoints = false;
          
          if(stopItem)
@@ -551,8 +543,10 @@ class Debugger
 
    void ChangeState(DebuggerState value)
    {
+      bool same = value == state;
+      // if(same) PrintLn("Debugger::ChangeState -- changing to same state");
       state = value;
-      if(ide) ide.AdjustDebugMenus();
+      if(!same && ide) ide.AdjustDebugMenus();
    }
 
    void CleanUp()
@@ -616,7 +610,7 @@ class Debugger
       sysBPs.Add(Breakpoint { type = internalWinMain, enabled = true, level = -1 });
 #endif
       sysBPs.Add(Breakpoint { type = internalModulesLoaded, enabled = true, level = -1 });
-      
+      sysBPs.Add(Breakpoint { type = internalModuleLoad, enabled = true, level = -1 });
    }
 
    ~Debugger()
@@ -641,10 +635,7 @@ class Debugger
       if(state == running)
       {
          if(targetProcessId)
-         {
-            //ide.AdjustDebugMenus();
             GdbDebugBreak(false);
-         }
       }
    }
 
@@ -667,7 +658,7 @@ class Debugger
       }
    }
 
-   void Restart(CompilerConfig compiler, ProjectConfig config)
+   void Restart(CompilerConfig compiler, ProjectConfig config, int bitDepth)
    {
       switch(state)
       {
@@ -682,7 +673,7 @@ class Debugger
             GdbAbortExec();
          case none:
          case terminated:
-            if(!GdbInit(compiler, config))
+            if(!GdbInit(compiler, config, bitDepth))
                break;
          case loaded:
             GdbExecRun();
@@ -696,7 +687,7 @@ class Debugger
       codloc = CodeLocation::ParseCodeLocation(location);
       if(codloc)
       {
-         CodeEditor editor = (CodeEditor)ide.OpenFile(codloc.absoluteFile, normal, true, null, no, normal);
+         CodeEditor editor = (CodeEditor)ide.OpenFile(codloc.absoluteFile, normal, true, null, no, normal, false);
          if(editor)
          {
             EditBox editBox = editor.editBox;
@@ -731,8 +722,8 @@ class Debugger
             {
                char * s;
                char title[MAX_LOCATION];
-
-               sprintf(title, $"Provide source file location for %s", (s = CopySystemPath(frame.file)));
+               snprintf(title, sizeof(title), $"Provide source file location for %s", (s = CopySystemPath(frame.file)));
+               title[sizeof(title)-1] = 0;
                delete s;
                if(SourceDirDialog(title, ide.workspace.projectDir, frame.file, sourceDir))
                {
@@ -741,7 +732,7 @@ class Debugger
                }
             }
             if(frame.absoluteFile)
-               editor = (CodeEditor)ide.OpenFile(frame.absoluteFile, normal, true, null, no, normal);
+               editor = (CodeEditor)ide.OpenFile(frame.absoluteFile, normal, true, null, no, normal, false);
             ide.Update(null);
             if(editor && frame.line)
             {
@@ -806,7 +797,10 @@ class Debugger
       targetProcessId = 0;
 
       if(code)
-         sprintf(verboseExitCode, $" with exit code %s", code);
+      {
+         snprintf(verboseExitCode, sizeof(verboseExitCode), $" with exit code %s", code);
+         verboseExitCode[sizeof(verboseExitCode)-1] = 0;
+      }
       else
          verboseExitCode[0] = '\0';
       
@@ -825,8 +819,6 @@ class Debugger
          }
       }
 
-      //ide.AdjustDebugMenus();
-
 #if defined(__unix__)
       progThread.terminate = true;
       if(fifoFile)
@@ -856,14 +848,14 @@ class Debugger
       ide.Update(null);
    }
       
-   void Start(CompilerConfig compiler, ProjectConfig config)
+   void Start(CompilerConfig compiler, ProjectConfig config, int bitDepth)
    {
       ide.outputView.debugBox.Clear();
       switch(state)
       {
          case none:
          case terminated:
-            if(!GdbInit(compiler, config))
+            if(!GdbInit(compiler, config, bitDepth))
                break;
          case loaded:
             GdbExecRun();
@@ -871,13 +863,13 @@ class Debugger
       }
    }
 
-   void StepInto(CompilerConfig compiler, ProjectConfig config)
+   void StepInto(CompilerConfig compiler, ProjectConfig config, int bitDepth)
    {
       switch(state)
       {
          case none:
          case terminated:
-            if(!GdbInit(compiler, config)) 
+            if(!GdbInit(compiler, config, bitDepth)) 
                break;
          case loaded:
             ide.outputView.ShowClearSelectTab(debug);
@@ -891,13 +883,13 @@ class Debugger
       }
    }
 
-   void StepOver(CompilerConfig compiler, ProjectConfig config, bool ignoreBkpts)
+   void StepOver(CompilerConfig compiler, ProjectConfig config, int bitDepth, bool ignoreBkpts)
    {
       switch(state)
       {
          case none:
          case terminated:
-            if(!GdbInit(compiler, config)) 
+            if(!GdbInit(compiler, config, bitDepth)) 
                break;
          case loaded:
             ide.outputView.ShowClearSelectTab(debug);
@@ -926,7 +918,7 @@ class Debugger
       }
    }
 
-   void RunToCursor(CompilerConfig compiler, ProjectConfig config, char * absoluteFilePath, int lineNumber, bool ignoreBkpts)
+   void RunToCursor(CompilerConfig compiler, ProjectConfig config, int bitDepth, char * absoluteFilePath, int lineNumber, bool ignoreBkpts, bool atSameLevel)
    {
       char relativeFilePath[MAX_LOCATION];
       DebuggerState oldState = state;
@@ -937,7 +929,7 @@ class Debugger
       {
          case none:
          case terminated:
-            Start(compiler, config);
+            Start(compiler, config, bitDepth);
          case stopped:
          case loaded:
             if(symbols)
@@ -947,7 +939,7 @@ class Debugger
                   ide.outputView.ShowClearSelectTab(debug);
                   ide.outputView.debugBox.Logf($"Starting debug mode\n");
                }
-               RunToCursorPrepare(absoluteFilePath, relativeFilePath, lineNumber);
+               RunToCursorPrepare(absoluteFilePath, relativeFilePath, lineNumber, atSameLevel);
                sentBreakInsert = true;
                GdbCommand(false, "-break-insert %s:%d", relativeFilePath, lineNumber);
                bpRunToCursor.bp = bpItem;
@@ -984,7 +976,7 @@ class Debugger
       else
       {
          *error = signalOn && activeThread == signalThread;
-         *lineCursor = activeFrameLevel + 1;
+         *lineCursor = activeFrameLevel - ((frameCount > 192 && activeFrameLevel > 191) ? frameCount - 192 - 1 : 0) + 1;
          *lineTopFrame = activeFrameLevel ? 1 : 0;
       }
    }
@@ -1052,7 +1044,7 @@ class Debugger
       else if(expression)
       {
          wh = Watch { };
-         row.tag = (int)wh;
+         row.tag = (int64)wh;
          ide.workspace.watches.Add(wh);
          wh.row = row;
          wh.expression = CopyString(expression);
@@ -1203,7 +1195,7 @@ class Debugger
       else
       {
          // FIXED: This is how it should have been... Source locations are only for files not in project
-         // if(eString_PathInsideOf(absolutePath, ide.workspace.projectDir))
+         // if(IsPathInsideOf(absolutePath, ide.workspace.projectDir))
          //   MakePathRelative(absolutePath, ide.workspace.projectDir, relativePath);
          bool result = false;
          if(prj)
@@ -1217,13 +1209,14 @@ class Debugger
             char title[MAX_LOCATION];
             char directory[MAX_LOCATION];
             StripLastDirectory(absolutePath, directory);
-            sprintf(title, $"Provide source files location directory for %s", absolutePath);
+            snprintf(title, sizeof(title), $"Provide source files location directory for %s", absolutePath);
+            title[sizeof(title)-1] = 0;
             while(true)
             {
                String srcDir = null;
                for(dir : ide.workspace.sourceDirs)
                {
-                  if(eString_PathInsideOf(absolutePath, dir))
+                  if(IsPathInsideOf(absolutePath, dir))
                   {
                      MakePathRelative(absoluteFilePath, dir, relativePath);
                      srcDir = dir;
@@ -1235,7 +1228,7 @@ class Debugger
                
                if(SourceDirDialog(title, directory, null, sourceDir))
                {
-                  if(eString_PathInsideOf(absolutePath, sourceDir))
+                  if(IsPathInsideOf(absolutePath, sourceDir))
                   {
                      AddSourceDir(sourceDir);
                      MakePathRelative(absoluteFilePath, sourceDir, relativePath);
@@ -1383,7 +1376,15 @@ class Debugger
                frame.line = atoi(item.value);
             else if(!strcmp(item.name, "fullname"))
             {
-               // New GDB is giving us a full name... Any reason why we coudln't figure it out ourselves?
+               // GDB 6.3 on OS X is giving "fullname" and "dir", all in absolute, but file name only in 'file'
+               String path = ide.workspace.GetPathWorkspaceRelativeOrAbsolute(item.value);
+               if(strcmp(frame.file, path))
+               {
+                  frame.file = path;
+                  delete frame.absoluteFile;
+                  frame.absoluteFile = ide.workspace.GetAbsolutePathFromRelative(frame.file);
+               }
+               delete path;
             }
             else
                DebuggerProtocolUnknown("Unknown frame member name", item.name);
@@ -1417,11 +1418,12 @@ class Debugger
    {
       if(gdbHandle)
       {
-         char string[MAX_F_STRING];
-         
+         // TODO: Improve this limit
+         static char string[MAX_F_STRING*4];
          va_list args;
          va_start(args, format);
-         vsprintf(string, format, args);
+         vsnprintf(string, sizeof(string), format, args);
+         string[sizeof(string)-1] = 0;
          va_end(args);
          
          gdbReady = false;
@@ -1438,8 +1440,9 @@ class Debugger
          if(ide.gdbDialog)
             ide.gdbDialog.AddCommand(string);
 #endif
-         gdbHandle.Printf("%s\n", string);
-         
+         strcat(string,"\n");
+         gdbHandle.Puts(string);
+
          if(focus)
             Process_ShowWindows(targetProcessId);
 
@@ -1451,7 +1454,7 @@ class Debugger
 
    bool ValidateBreakpoint(Breakpoint bp)
    {
-      if(modules)
+      if(modules && bp.bp)
       {
          if(bp.bp.line != bp.line)
          {
@@ -1478,13 +1481,13 @@ class Debugger
       return true;
    }
 
-   static void GdbInsertInternalBreakpoint()
+   static void GdbInsertInternalBreakpoints()
    {
       if(symbols)
       {
          //if(!breakpointsInserted)
          {
-            DirExpression objDir = ide.project.GetObjDir(currentCompiler, prjConfig);
+            DirExpression objDir = ide.project.GetObjDir(currentCompiler, prjConfig, bitDepth);
             for(bp : sysBPs)
             {
                if(!bp.inserted)
@@ -1517,7 +1520,8 @@ class Debugger
                      bool moduleLoadBlock = false;
                      File f;
                      ReplaceSpaces(fixedModuleName, ide.project.moduleName);
-                     sprintf(name, "%s.main.ec", fixedModuleName);
+                     snprintf(name, sizeof(name),"%s.main.ec", fixedModuleName);
+                     name[sizeof(name)-1] = 0;
                      strcpy(path, ide.workspace.projectDir);
                      PathCatSlash(path, objDir.dir);
                      PathCatSlash(path, name);
@@ -1550,11 +1554,40 @@ class Debugger
                            bp.bp = bpItem;
                            bpItem = null;
                            bp.inserted = (bp.bp && bp.bp.number != 0);
-                           ValidateBreakpoint(bp);
                         }
                         delete f;
                      }
-                     break;
+                  }
+                  else if(bp.type == internalModuleLoad && modules)
+                  {
+                     Project ecerePrj = null;
+                     for(p : ide.workspace.projects)
+                     {
+                        if(!strcmp(p.topNode.name, "ecere.epj"))
+                        {
+                           ecerePrj = p;
+                           break;
+                        }
+                     }
+                     if(ecerePrj)
+                     {
+                        ProjectNode node = ecerePrj.topNode.Find("instance.c", false);
+                        if(node)
+                        {
+                           char path[MAX_LOCATION];
+                           char relative[MAX_LOCATION];
+                           node.GetFullFilePath(path);
+                           bp.absoluteFilePath = CopyString(path);
+                           MakePathRelative(path, ecerePrj.topNode.path, relative);
+                           delete bp.relativeFilePath;
+                           bp.relativeFilePath = CopyString(relative);
+                           sentBreakInsert = true;
+                           GdbCommand(false, "-break-insert %s:InternalModuleLoadBreakpoint", bp.relativeFilePath);
+                           bp.bp = bpItem;
+                           bpItem = null;
+                           bp.inserted = (bp.bp && bp.bp.number != 0);
+                        }
+                     }
                   }
                }
             }
@@ -1578,7 +1611,17 @@ class Debugger
                   if(!ignoreBreakpoints && bp.enabled)
                   {
                      sentBreakInsert = true;
+                     breakpointError = false;
                      GdbCommand(false, "-break-insert %s:%d", bp.relativeFilePath, bp.line);
+                     // Improve, GdbCommand should return a success value?
+                     if(breakpointError)
+                     {
+                        char fileName[MAX_FILENAME];
+                        breakpointError = false;
+                        GetLastDirectory(bp.relativeFilePath, fileName);
+                        sentBreakInsert = true;
+                        GdbCommand(false, "-break-insert %s:%d", fileName, bp.line);
+                     }
                      bp.bp = bpItem;
                      bpItem = null;
                      bp.inserted = (bp.bp && bp.bp.number != 0);
@@ -1614,6 +1657,15 @@ class Debugger
       //breakpointsInserted = false;
       if(symbols)
       {
+         for(bp : sysBPs)
+         {
+            if(bp.bp)
+               GdbCommand(false, "-break-delete %d", bp.bp.number);
+            bp.inserted = false;
+            bp.bp = bpItem;
+            //check here (reply form -break-delete, returns bpitem?)
+            bpItem = null;
+         }
          for(bp : ide.workspace.breakpoints)
          {
             if(bp.bp)
@@ -1642,10 +1694,10 @@ class Debugger
       if(!frameCount)
          GdbCommand(false, "-stack-info-depth 192");
       if(frameCount && frameCount <= 192)
-         GdbCommand(false, "-stack-list-frames 0 191");
+         GdbCommand(false, "-stack-list-frames 0 %d", Min(frameCount-1, 191));
       else
       {
-         GdbCommand(false, "-stack-list-frames 0 95");
+         GdbCommand(false, "-stack-list-frames 0 %d", Min(frameCount-1, 95));
          GdbCommand(false, "-stack-list-frames %d %d", Max(frameCount - 96, 96), frameCount - 1);
       }
       GdbCommand(false, "");
@@ -1677,7 +1729,7 @@ class Debugger
             GdbCommand(false, "-environment-directory \"%s\"", dir);
             //GdbCommand(false, ""); // why this empty GDB command
          }
-         GdbInsertInternalBreakpoint();
+         GdbInsertInternalBreakpoints();
          targeted = true;
       }
       return true;
@@ -1701,11 +1753,7 @@ class Debugger
          if(internal)
             breakType = DebuggerAction::internal;
 
-         if(ide)
-         {
-            //ide.AdjustDebugMenus();
-            ide.Update(null);
-         }
+         if(ide) ide.Update(null);
          app.Unlock();
          if(Process_Break(targetProcessId))  //GdbCommand(false, "-exec-interrupt");
             serialSemaphore.Wait();
@@ -1713,7 +1761,6 @@ class Debugger
          {
             ChangeState(loaded);
             targetProcessId = 0;
-            //ide.AdjustDebugMenus();
          }
          app.Lock();
       }
@@ -1756,6 +1803,7 @@ class Debugger
    void GdbExecCommon()
    {
       ClearBreakDisplay();
+      GdbInsertInternalBreakpoints();
       GdbBreakpointsInsert();
    }
 
@@ -1806,14 +1854,14 @@ class Debugger
       return true;
    }
 
-   bool GdbInit(CompilerConfig compiler, ProjectConfig config)
+   bool GdbInit(CompilerConfig compiler, ProjectConfig config, int bitDepth)
    {
       bool result = true;
       char oldDirectory[MAX_LOCATION];
       char tempPath[MAX_LOCATION];
       char command[MAX_LOCATION];
       Project project = ide.project;
-      DirExpression targetDirExp = project.GetTargetDir(compiler, config);
+      DirExpression targetDirExp = project.GetTargetDir(compiler, config, bitDepth);
       PathBackup pathBackup { };
 
       if(currentCompiler != compiler)
@@ -1823,10 +1871,12 @@ class Debugger
          incref currentCompiler;
       }
       prjConfig = config;
+      this.bitDepth = bitDepth;
 
       ChangeState(loaded);
       sentKill = false;
       sentBreakInsert = false;
+      breakpointError = false;
       symbols = true;
       targeted = false;
       modules = false;
@@ -1861,7 +1911,7 @@ class Debugger
       else
          ChangeWorkingDir(ide.workspace.projectDir);
       
-      ide.SetPath(true, compiler, config);
+      ide.SetPath(true, compiler, config, bitDepth);
 
       // TODO: This pollutes the environment, but at least it works
       // It shouldn't really affect the IDE as the PATH gets restored and other variables set for testing will unlikely cause problems
@@ -1872,7 +1922,11 @@ class Debugger
          SetEnvironment(e.name, e.string);
       }
 
-      sprintf(command, "gdb -n -silent --interpreter=mi2"); //-async //\"%s\"
+      strcpy(command,
+         (compiler.targetPlatform == win32 && bitDepth == 64) ? "x86_64-w64-mingw32-gdb" :
+         (compiler.targetPlatform == win32 && bitDepth == 32) ? "i686-w64-mingw32-gdb" :
+         "gdb");
+      strcat(command, " -n -silent --interpreter=mi2"); //-async //\"%s\"
       gdbTimer.Start();
       gdbHandle = DualPipeOpen(PipeOpenMode { output = 1, error = 2, input = 1 }, command);
       if(!gdbHandle)
@@ -1900,7 +1954,6 @@ class Debugger
             if(!GdbTargetSet())
             {
                //ChangeState(terminated);
-               //ide.AdjustDebugMenus();
                result = false;
             }
 
@@ -1918,7 +1971,7 @@ class Debugger
                   else
                   {
                      //app.Lock();
-                     ide.outputView.debugBox.Logf($"err: Unable to create FIFO %s\n", progFifoPath);
+                     ide.outputView.debugBox.Logf(createFIFOMsg, progFifoPath);
                      //app.Unlock();
                   }
                }
@@ -1996,7 +2049,6 @@ class Debugger
       
       ide.outputView.debugBox.Logf($"Debugging stopped\n");
       ClearBreakDisplay();
-      //ide.AdjustDebugMenus();
       ide.Update(null);
 
 #if defined(__unix__)
@@ -2030,14 +2082,14 @@ class Debugger
       
       strcpy(path, ide.workspace.projectDir);
       PathCat(path, tempPath);
-      codeEditor = (CodeEditor)ide.OpenFile(path, Normal, false, null, no);
+      codeEditor = (CodeEditor)ide.OpenFile(path, Normal, false, null, no, normal, false);
       if(!codeEditor)
       {
          for(srcDir : ide.workspace.sourceDirs)
          {
             strcpy(path, srcDir);
             PathCat(path, tempPath);
-            codeEditor = (CodeEditor)ide.OpenFile(path, Normal, false, null, no);
+            codeEditor = (CodeEditor)ide.OpenFile(path, Normal, false, null, no, normal, false);
             if(codeEditor) break;
          }
       }
@@ -2048,7 +2100,7 @@ class Debugger
       if(!activeFrame || !activeFrame.absoluteFile)
          codeEditor = null;
       else
-         codeEditor = (CodeEditor)ide.OpenFile(activeFrame.absoluteFile, normal, false, null, no, normal);
+         codeEditor = (CodeEditor)ide.OpenFile(activeFrame.absoluteFile, normal, false, null, no, normal, false);
       if(codeEditor)
       {
          codeEditor.inUseDebug = true;
@@ -2259,11 +2311,11 @@ class Debugger
                switch(exp.type)
                {
                   case symbolErrorExp:
-                     sprintf(watchmsg, $"Symbol \"%s\" not found", exp.identifier.string);
+                     snprintf(watchmsg, sizeof(watchmsg), $"Symbol \"%s\" not found", exp.identifier.string);
                      break;
                   case structMemberSymbolErrorExp:
                      // todo get info as in next case (ExpClassMemberSymbolError)
-                     sprintf(watchmsg, $"Error: Struct member not found for \"%s\"", wh.expression);
+                     snprintf(watchmsg, sizeof(watchmsg), $"Error: Struct member not found for \"%s\"", wh.expression);
                      break;
                   case classMemberSymbolErrorExp:
                      {
@@ -2278,37 +2330,37 @@ class Debugger
                            {
                               char string[256] = "";
                               Symbol classSym;
-                              PrintType(type, string, false, true);
+                              PrintTypeNoConst(type, string, false, true);
                               classSym = FindClass(string);
                               _class = classSym ? classSym.registered : null;
                            }
                            if(_class)
-                              sprintf(watchmsg, $"Member \"%s\" not found in class \"%s\"", memberID ? memberID.string : "", _class.name);
+                              snprintf(watchmsg, sizeof(watchmsg), $"Member \"%s\" not found in class \"%s\"", memberID ? memberID.string : "", _class.name);
                            else
-                              sprintf(watchmsg, "Member \"%s\" not found in unregistered class? (Should never get this message)", memberID ? memberID.string : "");
+                              snprintf(watchmsg, sizeof(watchmsg), "Member \"%s\" not found in unregistered class? (Should never get this message)", memberID ? memberID.string : "");
                         }
                         else
-                           sprintf(watchmsg, "Member \"%s\" not found in no type? (Should never get this message)", memberID ? memberID.string : "");
+                           snprintf(watchmsg, sizeof(watchmsg), "Member \"%s\" not found in no type? (Should never get this message)", memberID ? memberID.string : "");
                      }
                      break;
                   case memoryErrorExp:
                      // Need to ensure when set to memoryErrorExp, constant is set
-                     sprintf(watchmsg, $"Memory can't be read at %s", /*(exp.type == constantExp) ? */exp.constant /*: null*/);
+                     snprintf(watchmsg, sizeof(watchmsg), $"Memory can't be read at %s", /*(exp.type == constantExp) ? */exp.constant /*: null*/);
                      break;
                   case dereferenceErrorExp:
-                     sprintf(watchmsg, $"Dereference failure for \"%s\"", wh.expression);
+                     snprintf(watchmsg, sizeof(watchmsg), $"Dereference failure for \"%s\"", wh.expression);
                      break;
                   case unknownErrorExp:
-                     sprintf(watchmsg, $"Unknown error for \"%s\"", wh.expression);
+                     snprintf(watchmsg, sizeof(watchmsg), $"Unknown error for \"%s\"", wh.expression);
                      break;
                   case noDebuggerErrorExp:
-                     sprintf(watchmsg, $"Debugger required for symbol evaluation in \"%s\"", wh.expression);
+                     snprintf(watchmsg, sizeof(watchmsg), $"Debugger required for symbol evaluation in \"%s\"", wh.expression);
                      break;
                   case debugStateErrorExp:
-                     sprintf(watchmsg, $"Incorrect debugger state for symbol evaluation in \"%s\"", wh.expression);
+                     snprintf(watchmsg, sizeof(watchmsg), $"Incorrect debugger state for symbol evaluation in \"%s\"", wh.expression);
                      break;
                   case 0:
-                     sprintf(watchmsg, $"Null type for \"%s\"", wh.expression);
+                     snprintf(watchmsg, sizeof(watchmsg), $"Null type for \"%s\"", wh.expression);
                      break;
                   case constantExp:
                   case stringExp:
@@ -2322,7 +2374,7 @@ class Debugger
 
                         if(exp.expType.kind != arrayType || exp.hasAddress)
                         {
-                           uint address;
+                           uint64 address;
                            char * string;
                            char value[4196];
                            int len;
@@ -2335,9 +2387,16 @@ class Debugger
                               sprintf(temp, "(char*)%s", exp.constant);*/
 
                            //evaluation = Debugger::EvaluateExpression(temp, &evalError);
-                           address = strtoul(exp.constant, null, 0);
+                           // address = strtoul(exp.constant, null, 0);
+                           address = _strtoui64(exp.constant, null, 0);
                            //printf("%x\n", address);
-                           sprintf(value, "0x%08x ", address);
+                           // snprintf(value, sizeof(value), "0x%08x ", address);
+
+                           if(address > 0xFFFFFFFFLL)
+                              snprintf(value, sizeof(value), (GetRuntimePlatform() == win32) ? "0x%016I64x " : "0x%016llx ", address);
+                           else
+                              snprintf(value, sizeof(value), (GetRuntimePlatform() == win32) ? "0x%08I64x " : "0x%08llx ", address);
+                           value[sizeof(value)-1] = 0;
                            
                            if(!address)
                               strcat(value, $"Null string");
@@ -2440,31 +2499,32 @@ class Debugger
                            }
                            else
                            {
-                              value = strtoul(exp.constant, null, 0);
+                              value = (uint)strtoul(exp.constant, null, 0);
                               signedValue = (int)value;
                            }
                         }
                         charString[0] = 0;
                         UTF32toUTF8Len(&value, 1, charString, 5);
                         if(value == '\0')
-                           sprintf(string, "\'\\0' (0)");
+                           snprintf(string, sizeof(string), "\'\\0' (0)");
                         else if(value == '\t')
-                           sprintf(string, "\'\\t' (%d)", value);
+                           snprintf(string, sizeof(string), "\'\\t' (%d)", value);
                         else if(value == '\n')
-                           sprintf(string, "\'\\n' (%d)", value);
+                           snprintf(string, sizeof(string), "\'\\n' (%d)", value);
                         else if(value == '\r')
-                           sprintf(string, "\'\\r' (%d)", value);
+                           snprintf(string, sizeof(string), "\'\\r' (%d)", value);
                         else if(wh.type.kind == charType && wh.type.isSigned)
-                           sprintf(string, "\'%s\' (%d)", charString, signedValue);
+                           snprintf(string, sizeof(string), "\'%s\' (%d)", charString, signedValue);
                         else if(value > 256 || wh.type.kind != charType)
                         {
                            if(value > 0x10FFFF || !GetCharCategory(value))
-                              sprintf(string, $"Invalid Unicode Keypoint (0x%08X)", value);
+                              snprintf(string, sizeof(string), $"Invalid Unicode Keypoint (0x%08X)", value);
                            else
-                              sprintf(string, "\'%s\' (U+%04X)", charString, value);
+                              snprintf(string, sizeof(string), "\'%s\' (U+%04X)", charString, value);
                         }
                         else
-                           sprintf(string, "\'%s\' (%d)", charString, value);
+                           snprintf(string, sizeof(string), "\'%s\' (%d)", charString, value);
+                        string[sizeof(string)-1] = 0;
                         
                         wh.value = CopyString(string);
                         result = true;
@@ -2478,23 +2538,23 @@ class Debugger
                   default:
                      if(exp.hasAddress)
                      {
-                        wh.value = PrintHexUInt(exp.address);
+                        wh.value = PrintHexUInt64(exp.address);
                         result = (bool)exp.address;
                      }
                      else
                      {
                         char tempString[256];
                         if(exp.member.memberType == propertyMember)
-                           sprintf(watchmsg, $"Missing property evaluation support for \"%s\"", wh.expression);
+                           snprintf(watchmsg, sizeof(watchmsg), $"Missing property evaluation support for \"%s\"", wh.expression);
                         else
-                           sprintf(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;
                }
             }
             else
-               sprintf(watchmsg, $"Invalid expression: \"%s\"", wh.expression);
+               snprintf(watchmsg, sizeof(watchmsg), $"Invalid expression: \"%s\"", wh.expression);
             if(exp) FreeExpression(exp);
 
             
@@ -2507,6 +2567,7 @@ class Debugger
          //else 
          //   wh.value = CopyString("No source file found for selected frame");
          
+         watchmsg[sizeof(watchmsg)-1] = 0;
          if(!wh.value)
             wh.value = CopyString(watchmsg);
       }
@@ -2531,7 +2592,7 @@ class Debugger
    }
 
    // to be removed... use GdbReadMemory that returns a byte array instead
-   char * ::GdbReadMemoryString(uint address, int size, char format, int rows, int cols)
+   char * ::GdbReadMemoryString(uint64 address, int size, char format, int rows, int cols)
    {
       eval.active = true;
       eval.error = none;
@@ -2539,17 +2600,25 @@ class Debugger
       if(!size)
          printf("GdbReadMemoryString called with size = 0!\n");
 #endif
-      GdbCommand(false, "-data-read-memory 0x%08x %c, %d, %d, %d", address, format, size, rows, cols);
+      // GdbCommand(false, "-data-read-memory 0x%08x %c, %d, %d, %d", address, format, size, rows, cols);
+      if(GetRuntimePlatform() == win32)
+         GdbCommand(false, "-data-read-memory 0x%016I64x %c, %d, %d, %d", address, format, size, rows, cols);
+      else
+         GdbCommand(false, "-data-read-memory 0x%016llx %c, %d, %d, %d", address, format, size, rows, cols);
       if(eval.active)
          ide.outputView.debugBox.Logf("Debugger Error: GdbReadMemoryString\n");
       return eval.result;
    }
 
-   byte * ::GdbReadMemory(uint address, int bytes)
+   byte * ::GdbReadMemory(uint64 address, int bytes)
    {
       eval.active = true;
       eval.error = none;
-      GdbCommand(false, "-data-read-memory 0x%08x %c, 1, 1, %d", address, 'u', bytes);
+      //GdbCommand(false, "-data-read-memory 0x%08x %c, 1, 1, %d", address, 'u', bytes);
+      if(GetRuntimePlatform() == win32)
+         GdbCommand(false, "-data-read-memory 0x%016I64x %c, 1, 1, %d", address, 'u', bytes);
+      else
+         GdbCommand(false, "-data-read-memory 0x%016llx %c, 1, 1, %d", address, 'u', bytes);
 #ifdef _DEBUG
       if(!bytes)
          printf("GdbReadMemory called with bytes = 0!\n");
@@ -2583,17 +2652,13 @@ class Debugger
    {
       bool conditionMet = true;
       Breakpoint bp = bpHit;
-      
+
       if(!bp && bpRunToCursor)
-      {
          bp = bpRunToCursor;
-         if(symbols)
-            GdbCommand(false, "-break-delete %d", bp.bp.number);
-      }
       
       if(bp)
       {
-         if(bp.type == user && bp.line != stopItem.frame.line)
+         if(bp.type == user && stopItem.frame.line && bp.line != stopItem.frame.line)
          {
             bp.line = stopItem.frame.line;
             ide.breakpointsView.UpdateBreakpoint(bp.row);
@@ -2611,8 +2676,7 @@ class Debugger
                   // Why was SelectFrame missing here?
                   SelectFrame(activeFrameLevel);
                   GoToStackFrameLine(activeFrameLevel, true);
-                  //ide.AdjustDebugMenus();
-                  ide.Activate();
+                  ideMainFrame.Activate();   // TOFIX: ide.Activate() is not reliable (app inactive)
                   ide.Update(null);
                }
                else
@@ -2620,6 +2684,11 @@ class Debugger
                break;
             case internalModulesLoaded:
                modules = true;
+               GdbInsertInternalBreakpoints();
+               GdbBreakpointsInsert();
+               GdbExecContinue(false);
+               break;
+            case internalModuleLoad:
                GdbBreakpointsInsert();
                GdbExecContinue(false);
                break;
@@ -2637,14 +2706,8 @@ class Debugger
                      // Why was SelectFrame missing here?
                      SelectFrame(activeFrameLevel);
                      GoToStackFrameLine(activeFrameLevel, true);
-                     //ide.AdjustDebugMenus();
-                     ide.Activate();
+                     ideMainFrame.Activate();   // TOFIX: ide.Activate() is not reliable (app inactive)
                      ide.Update(null);
-                     if(bp.type == BreakpointType::runToCursor)
-                     {
-                        delete bpRunToCursor;
-                        bpRunToCursor = null;
-                     }
                   }
                   else
                   {
@@ -2660,6 +2723,13 @@ class Debugger
       }
       else
          ide.outputView.debugBox.Logf("Debugger Error: Breakpoint hit could not match breakpoint instance\n");
+
+      if(bpRunToCursor)
+      {
+         if(symbols && bpRunToCursor.inserted)
+            GdbCommand(false, "-break-delete %d", bpRunToCursor.bp.number);
+         delete bpRunToCursor;
+      }
    }
 
    void GdbThreadExit()
@@ -2669,7 +2739,6 @@ class Debugger
          ChangeState(terminated);
          targetProcessId = 0;
          ClearBreakDisplay();
-         //ide.AdjustDebugMenus();
 
          if(gdbHandle)
          {
@@ -2971,7 +3040,7 @@ class Debugger
                            else if(!strcmp(item.name, "next-row"))
                            {
                               StripQuotes(item.value, item.value);
-                              eval.nextBlockAddress = strtoul(item.value, null, 0);
+                              eval.nextBlockAddress = _strtoui64(item.value, null, 0);
                            }
                            else if(!strcmp(item.name, "memory"))
                            {
@@ -3015,9 +3084,8 @@ class Debugger
             else if(!strcmp(outTokens[0], "^exit"))
             {
                ChangeState(terminated);
-               //ide.AdjustDebugMenus();
                // ide.outputView.debugBox.Logf("Exit\n");
-               //ide.Update(null);
+               // ide.Update(null);
                gdbReady = true;
                serialSemaphore.Release();
             }
@@ -3026,6 +3094,7 @@ class Debugger
                if(sentBreakInsert)
                {
                   sentBreakInsert = false;
+                  breakpointError = true;
 #ifdef _DEBUG
                   if(bpItem)
                      printf("problem\n");
@@ -3064,7 +3133,6 @@ class Debugger
                      {
                         ChangeState(loaded);
                         targetProcessId = 0;
-                        //ide.AdjustDebugMenus();
                      }
                      else if(!strcmp(item.value, "Function \\\"WinMain\\\" not defined."))
                      {
@@ -3073,19 +3141,16 @@ class Debugger
                      {
                         ChangeState(loaded);
                         targetProcessId = 0;
-                        //ide.AdjustDebugMenus();
                      }
                      else if(strstr(item.value, "No such file or directory."))
                      {
                         ChangeState(loaded);
                         targetProcessId = 0;
-                        //ide.AdjustDebugMenus();
                      }
                      else if(strstr(item.value, "During startup program exited with code "))
                      {
                         ChangeState(loaded);
                         targetProcessId = 0;
-                        //ide.AdjustDebugMenus();
                      }
                      else
                      {
@@ -3135,179 +3200,180 @@ class Debugger
                }
                else if(!strcmp(outTokens[0], "*stopped"))
                {
+                  int tk;
                   ChangeState(stopped);
-                  
-                  if(outTokens.count > 1 && TokenizeListItem(outTokens[1], item))
+
+                  for(tk = 1; tk < outTokens.count; tk++)
                   {
-                     if(!strcmp(item.name, "reason"))
+                     if(TokenizeListItem(outTokens[tk], item))
                      {
-                        char * reason = item.value;
-                        StripQuotes(reason, reason);
-                        if(!strcmp(reason, "exited-normally") || !strcmp(reason, "exited") || !strcmp(reason, "exited-signalled"))
+                        if(!strcmp(item.name, "reason"))
                         {
-                           char * exitCode;
-                           if(outTokens.count > 2 && TokenizeListItem(outTokens[2], item2))
+                           char * reason = item.value;
+                           StripQuotes(reason, reason);
+                           if(!strcmp(reason, "exited-normally") || !strcmp(reason, "exited") || !strcmp(reason, "exited-signalled"))
                            {
-                              StripQuotes(item2.value, item2.value);
-                              if(!strcmp(item2.name, "exit-code"))
-                                 exitCode = item2.value;
+                              char * exitCode;
+                              if(outTokens.count > tk+1 && TokenizeListItem(outTokens[tk+1], item2))
+                              {
+                                 tk++;
+                                 StripQuotes(item2.value, item2.value);
+                                 if(!strcmp(item2.name, "exit-code"))
+                                    exitCode = item2.value;
+                                 else
+                                    exitCode = null;
+                              }
                               else
                                  exitCode = null;
+                              HandleExit(reason, exitCode);
                            }
-                           else
-                              exitCode = null;
-                           HandleExit(reason, exitCode);
-                        }
-                        else if(!strcmp(reason, "breakpoint-hit"))
-                        {
-   #ifdef _DEBUG
-                           if(stopItem)
-                              printf("problem\n");
-   #endif
-                           stopItem = GdbDataStop { };
-
-                           for(i = 2; i < outTokens.count; i++)
+                           else if(!strcmp(reason, "breakpoint-hit"))
                            {
-                              TokenizeListItem(outTokens[i], item);
-                              StripQuotes(item.value, item.value);
-                              if(!strcmp(item.name, "bkptno"))
-                                 stopItem.bkptno = atoi(item.value);
-                              else if(!strcmp(item.name, "thread-id"))
-                                 stopItem.threadid = atoi(item.value);
-                              else if(!strcmp(item.name, "frame"))
+      #ifdef _DEBUG
+                              if(stopItem)
+                                 printf("problem\n");
+      #endif
+                              stopItem = GdbDataStop { };
+
+                              for(i = tk+1; i < outTokens.count; i++)
                               {
-                                 item.value = StripCurlies(item.value);
-                                 ParseFrame(stopItem.frame, item.value);
+                                 TokenizeListItem(outTokens[i], item);
+                                 StripQuotes(item.value, item.value);
+                                 if(!strcmp(item.name, "bkptno"))
+                                    stopItem.bkptno = atoi(item.value);
+                                 else if(!strcmp(item.name, "thread-id"))
+                                    stopItem.threadid = atoi(item.value);
+                                 else if(!strcmp(item.name, "frame"))
+                                 {
+                                    item.value = StripCurlies(item.value);
+                                    ParseFrame(stopItem.frame, item.value);
+                                 }
+                                 else
+                                    DebuggerProtocolUnknown("Unknown breakpoint hit item name", item.name);
                               }
-                              else
-                                 DebuggerProtocolUnknown("Unknown breakpoint hit item name", item.name);
-                           }
-
-                           event = hit;
-                        }
-                        else if(!strcmp(reason, "end-stepping-range"))
-                        {
-   #ifdef _DEBUG
-                           if(stopItem)
-                              printf("problem\n");
-   #endif
-                           stopItem = GdbDataStop { };
 
-                           for(i = 2; i < outTokens.count; i++)
+                              event = hit;
+                           }
+                           else if(!strcmp(reason, "end-stepping-range"))
                            {
-                              TokenizeListItem(outTokens[i], item);
-                              StripQuotes(item.value, item.value);
-                              if(!strcmp(item.name, "thread-id"))
-                                 stopItem.threadid = atoi(item.value);
-                              else if(!strcmp(item.name, "frame"))
+      #ifdef _DEBUG
+                              if(stopItem)
+                                 printf("problem\n");
+      #endif
+                              stopItem = GdbDataStop { };
+
+                              for(i = tk+1; i < outTokens.count; i++)
                               {
-                                 item.value = StripCurlies(item.value);
-                                 ParseFrame(stopItem.frame, item.value);
+                                 TokenizeListItem(outTokens[i], item);
+                                 StripQuotes(item.value, item.value);
+                                 if(!strcmp(item.name, "thread-id"))
+                                    stopItem.threadid = atoi(item.value);
+                                 else if(!strcmp(item.name, "frame"))
+                                 {
+                                    item.value = StripCurlies(item.value);
+                                    ParseFrame(stopItem.frame, item.value);
+                                 }
+                                 else if(!strcmp(item.name, "reason"))
+                                    ;
+                                 else if(!strcmp(item.name, "bkptno"))
+                                    ;
+                                 else
+                                    DebuggerProtocolUnknown("Unknown end of stepping range item name", item.name);
                               }
-                              else if(!strcmp(item.name, "reason"))
-                                 ;
-                              else if(!strcmp(item.name, "bkptno"))
-                                 ;
-                              else
-                                 DebuggerProtocolUnknown("Unknown end of stepping range item name", item.name);
-                           }
 
-                           event = stepEnd;
-                           //ide.AdjustDebugMenus();
-                           ide.Update(null);
-                        }
-                        else if(!strcmp(reason, "function-finished"))
-                        {
-   #ifdef _DEBUG
-                           if(stopItem)
-                              printf("problem\n");
-   #endif
-                           stopItem = GdbDataStop { };
-                           stopItem.reason = CopyString(reason);
-
-                           for(i = 2; i < outTokens.count; i++)
+                              event = stepEnd;
+                              ide.Update(null);
+                           }
+                           else if(!strcmp(reason, "function-finished"))
                            {
-                              TokenizeListItem(outTokens[i], item);
-                              StripQuotes(item.value, item.value);
-                              if(!strcmp(item.name, "thread-id"))
-                                 stopItem.threadid = atoi(item.value);
-                              else if(!strcmp(item.name, "frame"))
+      #ifdef _DEBUG
+                              if(stopItem)
+                                 printf("problem\n");
+      #endif
+                              stopItem = GdbDataStop { };
+                              stopItem.reason = CopyString(reason);
+
+                              for(i = tk+1; i < outTokens.count; i++)
                               {
-                                 item.value = StripCurlies(item.value);
-                                 ParseFrame(stopItem.frame, item.value);
+                                 TokenizeListItem(outTokens[i], item);
+                                 StripQuotes(item.value, item.value);
+                                 if(!strcmp(item.name, "thread-id"))
+                                    stopItem.threadid = atoi(item.value);
+                                 else if(!strcmp(item.name, "frame"))
+                                 {
+                                    item.value = StripCurlies(item.value);
+                                    ParseFrame(stopItem.frame, item.value);
+                                 }
+                                 else if(!strcmp(item.name, "gdb-result-var"))
+                                    stopItem.gdbResultVar = CopyString(item.value);
+                                 else if(!strcmp(item.name, "return-value"))
+                                    stopItem.returnValue = CopyString(item.value);
+                                 else
+                                    DebuggerProtocolUnknown("Unknown function finished item name", item.name);
                               }
-                              else if(!strcmp(item.name, "gdb-result-var"))
-                                 stopItem.gdbResultVar = CopyString(item.value);
-                              else if(!strcmp(item.name, "return-value"))
-                                 stopItem.returnValue = CopyString(item.value);
-                              else
-                                 DebuggerProtocolUnknown("Unknown function finished item name", item.name);
-                           }
 
-                           event = functionEnd;
-                           //ide.AdjustDebugMenus();
-                           ide.Update(null);
-                        }
-                        else if(!strcmp(reason, "signal-received"))
-                        {
-   #ifdef _DEBUG
-                           if(stopItem)
-                              printf("problem\n");
-   #endif
-                           stopItem = GdbDataStop { };
-                           stopItem.reason = CopyString(reason);
-
-                           for(i = 2; i < outTokens.count; i++)
+                              event = functionEnd;
+                              ide.Update(null);
+                           }
+                           else if(!strcmp(reason, "signal-received"))
                            {
-                              TokenizeListItem(outTokens[i], item);
-                              StripQuotes(item.value, item.value);
-                              if(!strcmp(item.name, "signal-name"))
-                                 stopItem.name = CopyString(item.value);
-                              else if(!strcmp(item.name, "signal-meaning"))
-                                 stopItem.meaning = CopyString(item.value);
-                              else if(!strcmp(item.name, "thread-id"))
-                                 stopItem.threadid = atoi(item.value);
-                              else if(!strcmp(item.name, "frame"))
+      #ifdef _DEBUG
+                              if(stopItem)
+                                 printf("problem\n");
+      #endif
+                              stopItem = GdbDataStop { };
+                              stopItem.reason = CopyString(reason);
+
+                              for(i = tk+1; i < outTokens.count; i++)
+                              {
+                                 TokenizeListItem(outTokens[i], item);
+                                 StripQuotes(item.value, item.value);
+                                 if(!strcmp(item.name, "signal-name"))
+                                    stopItem.name = CopyString(item.value);
+                                 else if(!strcmp(item.name, "signal-meaning"))
+                                    stopItem.meaning = CopyString(item.value);
+                                 else if(!strcmp(item.name, "thread-id"))
+                                    stopItem.threadid = atoi(item.value);
+                                 else if(!strcmp(item.name, "frame"))
+                                 {
+                                    item.value = StripCurlies(item.value);
+                                    ParseFrame(stopItem.frame, item.value);
+                                 }
+                                 else
+                                    DebuggerProtocolUnknown("Unknown signal reveived item name", item.name);
+                              }
+                              if(!strcmp(stopItem.name, "SIGTRAP"))
                               {
-                                 item.value = StripCurlies(item.value);
-                                 ParseFrame(stopItem.frame, item.value);
+                                 switch(breakType)
+                                 {
+                                    case internal:
+                                       breakType = none;
+                                       break;
+                                    case restart:
+                                    case stop:
+                                       break;
+                                    default:
+                                       event = breakEvent;
+                                 }
                               }
                               else
-                                 DebuggerProtocolUnknown("Unknown signal reveived item name", item.name);
-                           }
-                           if(!strcmp(stopItem.name, "SIGTRAP"))
-                           {
-                              switch(breakType)
                               {
-                                 case internal:
-                                    breakType = none;
-                                    break;
-                                 case restart:
-                                 case stop:
-                                    break;
-                                 default:
-                                    event = breakEvent;
-                                    //ide.AdjustDebugMenus(); ide.Update(null);
+                                 event = signal;
                               }
                            }
+                           else if(!strcmp(reason, "watchpoint-trigger"))
+                              DebuggerProtocolUnknown("Reason watchpoint trigger not handled", "");
+                           else if(!strcmp(reason, "read-watchpoint-trigger"))
+                              DebuggerProtocolUnknown("Reason read watchpoint trigger not handled", "");
+                           else if(!strcmp(reason, "access-watchpoint-trigger"))
+                              DebuggerProtocolUnknown("Reason access watchpoint trigger not handled", "");
+                           else if(!strcmp(reason, "watchpoint-scope"))
+                              DebuggerProtocolUnknown("Reason watchpoint scope not handled", "");
+                           else if(!strcmp(reason, "location-reached"))
+                              DebuggerProtocolUnknown("Reason location reached not handled", "");
                            else
-                           {
-                              event = signal;
-                              //ide.AdjustDebugMenus(); ide.Update(null);
-                           }
+                              DebuggerProtocolUnknown("Unknown reason", reason);
                         }
-                        else if(!strcmp(reason, "watchpoint-trigger"))
-                           DebuggerProtocolUnknown("Reason watchpoint trigger not handled", "");
-                        else if(!strcmp(reason, "read-watchpoint-trigger"))
-                           DebuggerProtocolUnknown("Reason read watchpoint trigger not handled", "");
-                        else if(!strcmp(reason, "access-watchpoint-trigger"))
-                           DebuggerProtocolUnknown("Reason access watchpoint trigger not handled", "");
-                        else if(!strcmp(reason, "watchpoint-scope"))
-                           DebuggerProtocolUnknown("Reason watchpoint scope not handled", "");
-                        else if(!strcmp(reason, "location-reached"))
-                           DebuggerProtocolUnknown("Reason location reached not handled", "");
-                        else
-                           DebuggerProtocolUnknown("Unknown reason", reason);
                      }
                   }
                   app.SignalEvent();
@@ -3334,10 +3400,7 @@ class Debugger
                   }
 
                   if(targetProcessId)
-                  {
                      ChangeState(running);
-                     //ide.AdjustDebugMenus(); ide.Update(null);
-                  }
                   else if(!oldProcessID)
                   {
                      ide.outputView.debugBox.Logf($"Debugger Error: No target process ID\n");
@@ -3359,7 +3422,6 @@ class Debugger
                      
                      ide.outputView.debugBox.Logf($"Debugging stopped\n");
                      ClearBreakDisplay();
-                     //ide.AdjustDebugMenus(); ide.Update(null);
 
                #if defined(__unix__)
                      if(FileExists(progFifoPath)) //fileCreated)
@@ -3419,7 +3481,7 @@ class Debugger
       delete item2;
    }
 
-   void RunToCursorPrepare(char * absoluteFilePath, char * relativeFilePath, int lineNumber)
+   void RunToCursorPrepare(char * absoluteFilePath, char * relativeFilePath, int lineNumber, bool atSameLevel)
    {
       if(bpRunToCursor)
       {
@@ -3438,7 +3500,7 @@ class Debugger
       bpRunToCursor.enabled = true;
       bpRunToCursor.condition = null;
       bpRunToCursor.ignore = 0;
-      bpRunToCursor.level = -1;
+      bpRunToCursor.level = atSameLevel ? frameCount - activeFrameLevel -1 : -1;
    }
 
    ExpressionType ::DebugEvalExpTypeError(char * result)
@@ -3471,7 +3533,7 @@ class Debugger
       return result;
    }
 
-   char * ::ReadMemory(uint address, int size, char format, ExpressionType * error)
+   char * ::ReadMemory(uint64 address, int size, char format, ExpressionType * error)
    {
       // check for state
       char * result = GdbReadMemoryString(address, size, format, 1, 1);
@@ -3500,9 +3562,9 @@ class GdbThread : Thread
          int result;
          app.Unlock();
          result = gdbHandle.Read(output, 1, sizeof(output));
+         app.Lock();
          if(debugger.state == terminated || !gdbHandle || gdbHandle.Eof())
             break;
-         app.Lock();
          if(result)
          {
             int c;
@@ -3551,6 +3613,9 @@ class GdbThread : Thread
    }
 }
 
+static define createFIFOMsg = $"err: Unable to create FIFO %s\n";
+static define openFIFOMsg = $"err: Unable to open FIFO %s for read\n";
+
 #if defined(__unix__)
 #define uint _uint
 #include <errno.h>
@@ -3589,17 +3654,12 @@ class ProgramThread : Thread
          if(!fifoFile)
          {
             app.Lock();
-            ide.outputView.debugBox.Logf($"err: Unable to open FIFO %s for read\n", progFifoPath);
+            ide.outputView.debugBox.Logf(openFIFOMsg, progFifoPath);
             app.Unlock();
          }
          else
          {
-#ifdef BSD
-            // TODO: Fix on BSD 
-            fd = 0;
-#else
-            fd = fileno(fifoFile.input);
-#endif
+            fd = fileno((FILE *)fifoFile.input);
             //fcntl(fd, F_SETFL, fcntl(fd, F_GETFL) | O_NONBLOCK);
          }
       }
@@ -3618,7 +3678,7 @@ class ProgramThread : Thread
          selectResult = select(fd + 1, &rs, null, null, &time);
          if(FD_ISSET(fd, &rs))
          {
-            int result = read(fd, output, sizeof(output)-1);
+            int result = (int)read(fd, output, sizeof(output)-1);
             if(!result || (result < 0 && errno != EAGAIN))
                break;
             if(result > 0)
@@ -3803,7 +3863,8 @@ class Breakpoint : struct
    char * LocationToString()
    {
       char location[MAX_LOCATION+20];
-      sprintf(location, "%s:%d", relativeFilePath, line);
+      snprintf(location, sizeof(location), "%s:%d", relativeFilePath, line);
+      location[sizeof(location)-1] = 0;
 #if defined(__WIN32__)
       ChangeCh(location, '/', '\\');
 #endif
@@ -3882,7 +3943,7 @@ struct DebugEvaluationData
    bool active;
    char * result;
    int bytes;
-   uint nextBlockAddress;
+   uint64 nextBlockAddress;
 
    DebuggerEvaluationError error;
 };