6 //#define GDB_DEBUG_CONSOLE
10 extern char * strrchr(char * s, char c);
22 #include <sys/time.h> // Required on Apple...
26 //bool eString_PathInsidePath(char * to, char * path)
27 bool eString_PathInsideOf(char * path, char * of)
29 if(!path[0] || !of[0])
30 return false; // What to do here? Ever used?
33 char ofPart[MAX_FILENAME], ofRest[MAX_LOCATION];
34 char pathPart[MAX_FILENAME], pathRest[MAX_LOCATION];
36 strcpy(pathRest, path);
37 for(; ofRest[0] && pathRest[0];)
39 SplitDirectory(ofRest, ofPart, ofRest);
40 SplitDirectory(pathRest, pathPart, pathRest);
41 if(fstrcmp(pathPart, ofPart))
44 if(!ofRest[0] && !pathRest[0]) // paths are identical - should return false or true? (changed to false)
46 else if(!pathRest[0]) // not inside of, it's the other way around
52 public char * StripQuotes2(char * string, char * output)
56 bool quoted = false, escaped = false;
58 for(c = 0; ch = string[c]; c++)
62 if(escaped || ch != '\"')
81 static void strescpy(char * d, char * s)
134 static char * CopyUnescapedSystemPath(char * p)
136 char * d = new char[strlen(p) + 1];
138 #if defined(__WIN32__)
139 ChangeCh(d, '/', '\\');
144 static char * CopyUnescapedUnixPath(char * p)
146 char * d = new char[strlen(p) + 1];
148 #if defined(__WIN32__)
149 ChangeCh(d, '\\', '/');
154 static char * CopyUnescapedString(char * s)
156 char * d = new char[strlen(s) + 1];
161 // String Unescape Copy
163 // TOFIX: THIS DOESN'T HANDLE NUMERIC ESCAPE CODES (OCTAL/HEXADECIMAL...)?
164 // Seems very similar to ReadString in pass15.ec (which also misses numeric escape codes :) )
166 static void struscpy(char * d, char * s)
218 static char * StripBrackets(char * string)
220 int length = strlen(string);
221 if(length > 1 && *string == '[' && string[length - 1] == ']')
224 string[length - 1] = '\0';
231 static char * StripCurlies(char * string)
233 int length = strlen(string);
234 if(length > 1 && *string == '{' && string[length - 1] == '}')
237 string[length - 1] = '\0';
244 static int StringGetInt(char * string, int start)
247 int i, len = strlen(string);
249 for(i = start; i < len && i < start + 8; i++)
251 if(string[i] == '0' || string[i] == '1' || string[i] == '2' || string[i] == '3' || string[i] == '4' || string[i] == '5' || string[i] == '6' || string[i] == '7' || string[i] == '8' || string[i] == '9')
252 strncat(number, &string[i], 1);
259 static int TokenizeList(char * string, const char seperator, Array<char *> tokens)
263 bool quoted = false; //bool escaped = false;
264 char * start = string;
266 for(; *string; string++)
275 else if(*string == '\"')
277 else if(*string == '{' || *string == '[' || *string == '(' || *string == '<')
279 else if(*string == '}' || *string == ']' || *string == ')' || *string == '>')
281 else if(*string == seperator && !level)
290 //tokens[count] = start;
291 //tokens[count++] = start;
298 static bool TokenizeListItem(char * string, DebugListItem item)
300 char * equal = strstr(string, "=");
314 static void DebuggerProtocolUnknown(char * message, char * gdbOutput)
316 #ifdef _DEBUG_GDB_PROTOCOL
317 ide.outputView.debugBox.Logf("Debugger Protocol Error: %s (%s)\n", message, gdbOutput);
321 // define GdbGetLineSize = 1638400;
322 define GdbGetLineSize = 5638400;
323 #if defined(__unix__)
324 char progFifoPath[MAX_LOCATION];
325 char progFifoDir[MAX_LOCATION];
328 enum DebuggerState { none, prompt, loaded, running, stopped, terminated };
329 enum DebuggerEvent { none, hit, breakEvent, signal, stepEnd, functionEnd, exit };
330 enum DebuggerAction { none, internal, restart, stop, selectFrame }; //, bpValidation
331 enum BreakpointType { none, internalMain, internalWinMain, internalModulesLoaded, user, runToCursor };
332 enum DebuggerEvaluationError { none, symbolNotFound, memoryCantBeRead, unknown };
334 FileDialog debuggerFileDialog { type = selectDir };
336 static DualPipe gdbHandle;
337 static DebugEvaluationData eval { };
339 static int targetProcessId;
341 static bool gdbReady;
345 Semaphore serialSemaphore { };
350 //bool breakpointsInserted;
352 bool sentBreakInsert;
353 bool ignoreBreakpoints;
354 bool userBreakOnInternBreak;
361 int activeFrameLevel;
372 DebuggerAction breakType;
373 //DebuggerCommand lastCommand; // THE COMPILER COMPILES STUFF THAT DOES NOT EXIST???
375 GdbDataStop stopItem;
376 GdbDataBreakpoint bpItem;
379 List<Breakpoint> sysBPs { };
380 Breakpoint bpRunToCursor;
386 ProjectConfig prjConfig;
388 CodeEditor codeEditor;
390 GdbThread gdbThread { debugger = this };
393 delay = 0.0, userData = this;
397 bool monitor = false;
398 DebuggerEvent curEvent = event;
399 GdbDataStop stopItem = this.stopItem;
405 this.stopItem = null;
408 if(curEvent && curEvent != exit)
411 printf("No stop item\n");
429 GdbCommand(false, "-stack-select-frame %d", activeFrameLevel);
430 for(activeFrame = stackFrames.first; activeFrame; activeFrame = activeFrame.next)
431 if(activeFrame.level == activeFrameLevel)
437 // GdbCommand(false, "-break-info %d", bpItem.number);
447 activeThread = stopItem.threadid;
448 GdbCommand(false, "-thread-list-ids");
453 Breakpoint bp = null;
455 for(i : ide.workspace.breakpoints; i.bp && i.bp.number == stopItem.bkptno)
462 for(i : sysBPs; i.bp && i.bp.number == stopItem.bkptno)
470 if(!(!userBreakOnInternBreak &&
471 bp && (bp.type == internalMain || bp.type == internalWinMain || bp.type == internalModulesLoaded)))
473 hitThread = stopItem.threadid;
477 signalThread = stopItem.threadid;
489 activeThread = stopItem.threadid;
490 GdbCommand(false, "-thread-list-ids");
492 if(activeFrameLevel > 0)
493 GdbCommand(false, "-stack-select-frame %d", activeFrameLevel);
495 WatchesCodeEditorLinkInit();
505 ide.outputView.debugBox.Logf("Signal received: %s - %s\n", stopItem.name, stopItem.meaning);
506 ide.outputView.debugBox.Logf(" %s:%d\n", (s = CopySystemPath(stopItem.frame.file)), stopItem.frame.line);
512 // Why was SelectFrame missing here?
513 SelectFrame(activeFrameLevel);
514 GoToStackFrameLine(activeFrameLevel, curEvent == signal || curEvent == stepEnd /*false*/);
517 if(curEvent == signal)
518 ide.outputView.Show();
519 if(curEvent == signal || curEvent == breakEvent)
521 if(curEvent == breakEvent)
522 ide.threadsView.Show();
523 ide.callStackView.Show();
525 ide.ShowCodeEditor();
526 if(curEvent == breakEvent)
527 ide.callStackView.Activate();
534 if(curEvent == DebuggerEvent::breakEvent || curEvent == stepEnd || curEvent == functionEnd)
535 ignoreBreakpoints = false;
546 #ifdef GDB_DEBUG_CONSOLE
547 char lastGdbOutput[GdbGetLineSize];
549 #if defined(__unix__)
550 ProgramThread progThread { };
555 // Stop(); // Don't need to call Stop here, because ~ProjectView() will call it explicitly.
557 stackFrames.Free(Frame::Free);
567 waitingForPID = false;
572 sentBreakInsert = false;
573 ignoreBreakpoints = false;
574 userBreakOnInternBreak = false;
577 activeFrameLevel = 0;
594 bpRunToCursor = null;
600 /*GdbThread gdbThread
606 ideProcessId = Process_GetCurrentProcessId();
608 sysBPs.Add(Breakpoint { type = internalMain, enabled = true, level = -1 });
609 #if defined(__WIN32__)
610 sysBPs.Add(Breakpoint { type = internalWinMain, enabled = true, level = -1 });
612 sysBPs.Add(Breakpoint { type = internalModulesLoaded, enabled = true, level = -1 });
624 property bool isActiveForCurrentConfig
628 return ide.project && ide.project.config == prjConfig && (state == running || state == stopped) ? true : false;
634 GdbExecContinue(true);
643 ide.DebugUpdateMenus(running, true);
644 GdbDebugBreak(false);
657 GdbDebugBreak(false);
668 property bool isInDebugMode
672 if(state == running || state == stopped)
686 GdbDebugBreak(false);
697 bool GoToCodeLine(char * location)
700 codloc = CodeLocation::ParseCodeLocation(location);
703 CodeEditor editor = (CodeEditor)ide.OpenFile(codloc.absoluteFile, normal, true, null, no, normal);
706 EditBox editBox = editor.editBox;
707 editBox.GoToLineNum(codloc.line - 1);
708 editBox.GoToPosition(editBox.line, codloc.line - 1, 0);
715 bool GoToStackFrameLine(int stackLevel, bool askForLocation)
719 char filePath[MAX_LOCATION];
720 char sourceDir[MAX_LOCATION];
722 CodeEditor editor = null;
723 if(stackLevel == -1) // this (the two lines) is part of that fix that I would not put in for some time
725 for(frame = stackFrames.first; frame; frame = frame.next)
726 if(frame.level == stackLevel)
730 ide.callStackView.Show();
732 if(!frame.absoluteFile && frame.file)
733 frame.absoluteFile = ide.workspace.GetAbsolutePathFromRelative(frame.file);
734 if(!frame.absoluteFile && askForLocation && frame.file)
737 char title[MAX_LOCATION];
739 sprintf(title, "Provide source file location for %s", (s = CopySystemPath(frame.file)));
741 if(SourceDirDialog(title, ide.workspace.projectDir, frame.file, sourceDir))
743 AddSourceDir(sourceDir);
744 frame.absoluteFile = ide.workspace.GetAbsolutePathFromRelative(frame.file);
747 if(frame.absoluteFile)
748 editor = (CodeEditor)ide.OpenFile(frame.absoluteFile, normal, true, null, no, normal);
750 if(editor && frame.line)
752 EditBox editBox = editor.editBox;
753 editBox.GoToLineNum(frame.line - 1);
754 editBox.GoToPosition(editBox.line, frame.line - 1, 0);
762 void SelectThread(int thread)
766 if(thread != activeThread)
768 activeFrameLevel = -1;
769 ide.callStackView.Clear();
770 GdbCommand(false, "-thread-select %d", thread);
772 // Why was SelectFrame missing here?
773 SelectFrame(activeFrameLevel);
774 GoToStackFrameLine(activeFrameLevel, true);
775 WatchesCodeEditorLinkRelease();
776 WatchesCodeEditorLinkInit();
780 ide.callStackView.Show();
784 void SelectFrame(int frame)
788 if(frame != activeFrameLevel || !codeEditor || !codeEditor.visible)
790 activeFrameLevel = frame; // there is no active frame number in the gdb reply
791 GdbCommand(false, "-stack-select-frame %d", activeFrameLevel);
792 for(activeFrame = stackFrames.first; activeFrame; activeFrame = activeFrame.next)
793 if(activeFrame.level == activeFrameLevel)
796 WatchesCodeEditorLinkRelease();
797 WatchesCodeEditorLinkInit();
804 void HandleExit(char * reason, char * code)
806 bool returnedExitCode = false;
807 char verboseExitCode[128];
813 sprintf(verboseExitCode, " with exit code %s", code);
815 verboseExitCode[0] = '\0';
819 // ClearBreakDisplay();
823 for(wh : ide.workspace.watches)
825 if(wh.type) FreeType(wh.type);
828 ide.watchesView.UpdateWatch(wh);
832 ide.DebugUpdateMenus(loaded, false);
834 #if defined(__unix__)
835 progThread.terminate = true;
838 fifoFile.CloseInput();
847 char program[MAX_LOCATION];
848 GetSystemPathBuffer(program, targetFile);
850 ide.outputView.debugBox.Logf("The program %s has exited%s.\n", program, verboseExitCode);
851 else if(!strcmp(reason, "exited-normally"))
852 ide.outputView.debugBox.Logf("The program %s has exited normally%s.\n", program, verboseExitCode);
853 else if(!strcmp(reason, "exited"))
854 ide.outputView.debugBox.Logf("The program %s has exited%s.\n", program, verboseExitCode);
855 else if(!strcmp(reason, "exited-signalled"))
856 ide.outputView.debugBox.Logf("The program %s has exited with a signal%s.\n", program, verboseExitCode);
858 ide.outputView.debugBox.Logf("The program %s has exited (gdb provided an unknown reason)%s.\n", program, verboseExitCode);
865 ide.outputView.debugBox.Clear();
887 ide.outputView.ShowClearSelectTab(debug);
888 ide.outputView.debugBox.Logf("Starting debug mode\n");
889 userBreakOnInternBreak = true;
898 void StepOver(bool ignoreBkpts)
907 ide.outputView.ShowClearSelectTab(debug);
908 ide.outputView.debugBox.Logf("Starting debug mode\n");
909 ignoreBreakpoints = ignoreBkpts;
910 userBreakOnInternBreak = true;
914 ignoreBreakpoints = ignoreBkpts;
915 if(ignoreBreakpoints)
916 GdbBreakpointsDelete(true);
922 void StepOut(bool ignoreBkpts)
926 ignoreBreakpoints = ignoreBkpts;
927 if(ignoreBreakpoints)
928 GdbBreakpointsDelete(true);
933 void RunToCursor(char * absoluteFilePath, int lineNumber, bool ignoreBkpts)
935 char relativeFilePath[MAX_LOCATION];
936 DebuggerState oldState = state;
937 ignoreBreakpoints = ignoreBkpts;
938 if(!ide.projectView.GetRelativePath(absoluteFilePath, relativeFilePath))
939 strcpy(relativeFilePath, absoluteFilePath);
951 ide.outputView.ShowClearSelectTab(debug);
952 ide.outputView.debugBox.Logf("Starting debug mode\n");
954 RunToCursorPrepare(absoluteFilePath, relativeFilePath, lineNumber);
955 sentBreakInsert = true;
956 GdbCommand(false, "-break-insert %s:%d", relativeFilePath, lineNumber);
957 bpRunToCursor.bp = bpItem;
959 bpRunToCursor.inserted = (bpRunToCursor.bp.number != 0);
960 ValidateBreakpoint(bpRunToCursor);
967 if(ignoreBreakpoints)
968 GdbBreakpointsDelete(false);
972 if(ignoreBreakpoints)
973 GdbBreakpointsDelete(false);
974 GdbExecContinue(true);
980 void GetCallStackCursorLine(bool * error, int * lineCursor, int * lineTopFrame)
982 if(activeFrameLevel == -1)
990 *error = signalOn && activeThread == signalThread;
991 *lineCursor = activeFrameLevel + 1;
992 *lineTopFrame = activeFrameLevel ? 1 : 0;
996 int GetMarginIconsLineNumbers(char * fileName, int lines[], bool enabled[], int max, bool * error, int * lineCursor, int * lineTopFrame)
998 char winFilePath[MAX_LOCATION];
999 char * absoluteFilePath = GetSlashPathBuffer(winFilePath, fileName);
1001 Iterator<Breakpoint> it { ide.workspace.breakpoints };
1002 while(it.Next() && count < max)
1004 Breakpoint bp = it.data;
1007 if(bp.absoluteFilePath && bp.absoluteFilePath[0] && !fstrcmp(bp.absoluteFilePath, absoluteFilePath))
1009 lines[count] = bp.line;
1010 enabled[count] = bp.enabled;
1015 if(activeFrameLevel == -1)
1023 *error = signalOn && activeThread == signalThread;
1024 if(activeFrame && activeFrame.absoluteFile && !fstrcmp(absoluteFilePath, activeFrame.absoluteFile))
1025 *lineCursor = activeFrame.line;
1028 if(activeFrame && stopItem && stopItem.frame && activeFrame.level == stopItem.frame.level)
1030 else if(stopItem && stopItem.frame && stopItem.frame.absoluteFile && !fstrcmp(absoluteFilePath, stopItem.frame.absoluteFile))
1031 *lineTopFrame = stopItem.frame.line;
1035 if(*lineTopFrame == *lineCursor && *lineTopFrame)
1041 void ChangeWatch(DataRow row, char * expression)
1043 Watch wh = (Watch)row.tag;
1046 delete wh.expression;
1048 wh.expression = CopyString(expression);
1051 Iterator<Watch> it { ide.workspace.watches };
1053 ide.workspace.watches.Delete(it.pointer);
1060 ide.workspace.watches.Add(wh);
1062 wh.expression = CopyString(expression);
1064 ide.workspace.Save();
1065 //if(expression && state == stopped)
1070 void MoveIcons(char * fileName, int lineNumber, int move, bool start)
1072 char winFilePath[MAX_LOCATION];
1073 char * absoluteFilePath = GetSlashPathBuffer(winFilePath, fileName);
1076 for(bpLink = ide.workspace.breakpoints.first; bpLink; bpLink = next)
1078 Breakpoint bp = (Breakpoint)bpLink.data;
1081 if(bp.type == user && bp.absoluteFilePath && !fstrcmp(bp.absoluteFilePath, absoluteFilePath))
1083 if(bp.line > lineNumber || (bp.line == lineNumber && start))
1085 if(move < 0 && (bp.line < lineNumber - move))
1086 ide.workspace.RemoveBreakpoint(bp);
1090 ide.breakpointsView.UpdateBreakpoint(bp.row);
1091 ide.workspace.Save();
1097 // moving code cursors is futile, on next step, stop, hit, cursors will be offset anyways
1100 bool SourceDirDialog(char * title, char * startDir, char * test, char * sourceDir)
1104 String srcDir = null;
1106 debuggerFileDialog.text = title;
1107 debuggerFileDialog.currentDirectory = startDir;
1108 debuggerFileDialog.master = ide;
1110 while(debuggerFileDialog.Modal())
1112 strcpy(sourceDir, debuggerFileDialog.filePath);
1113 if(!fstrcmp(ide.workspace.projectDir, sourceDir) &&
1114 MessageBox { type = yesNo, master = ide,
1115 contents = "This is the project directory.\nWould you like to try again?",
1116 text = "Invalid Source Directory" }.Modal() == no)
1120 for(dir : ide.workspace.sourceDirs)
1122 if(!fstrcmp(dir, sourceDir))
1130 MessageBox { type = yesNo, master = ide,
1131 contents = "This source directory is already specified.\nWould you like to try again?",
1132 text = "Invalid Source Directory" }.Modal() == no)
1138 char file[MAX_LOCATION];
1139 strcpy(file, sourceDir);
1140 PathCat(file, test);
1141 result = FileExists(file);
1143 MessageBox { type = yesNo, master = ide,
1144 contents = "Unable to locate source file.\nWould you like to try again?",
1145 text = "Invalid Source Directory" }.Modal() == no)
1159 void AddSourceDir(char * sourceDir)
1161 ide.workspace.sourceDirs.Add(CopyString(sourceDir));
1162 ide.workspace.Save();
1166 DebuggerState oldState = state;
1171 GdbDebugBreak(true);
1174 GdbCommand(false, "-environment-directory \"%s\"", sourceDir);
1177 if(oldState == running)
1178 GdbExecContinue(false);
1182 void ToggleBreakpoint(char * fileName, int lineNumber, Project prj)
1184 char winFilePath[MAX_LOCATION];
1185 char * absoluteFilePath = GetSlashPathBuffer(winFilePath, fileName);
1186 char absolutePath[MAX_LOCATION];
1187 char relativePath[MAX_LOCATION];
1188 char sourceDir[MAX_LOCATION];
1189 Breakpoint bp = null;
1191 strcpy(absolutePath, absoluteFilePath);
1192 for(i : ide.workspace.breakpoints; i.type == user && i.absoluteFilePath && !fstrcmp(i.absoluteFilePath, absolutePath) && i.line == lineNumber)
1201 ide.workspace.RemoveBreakpoint(bp);
1209 // FIXED: This is how it should have been... Source locations are only for files not in project
1210 // if(eString_PathInsideOf(absolutePath, ide.workspace.projectDir))
1211 // MakePathRelative(absolutePath, ide.workspace.projectDir, relativePath);
1212 bool result = false;
1214 result = prj.GetRelativePath(absolutePath, relativePath);
1216 ide.projectView.GetRelativePath(absolutePath, relativePath);
1217 //if(ide.projectView.GetRelativePath(absolutePath, relativePath));
1221 char title[MAX_LOCATION];
1222 char directory[MAX_LOCATION];
1223 StripLastDirectory(absolutePath, directory);
1224 sprintf(title, "Provide source files location directory for %s", absolutePath);
1227 String srcDir = null;
1228 for(dir : ide.workspace.sourceDirs)
1230 if(eString_PathInsideOf(absolutePath, dir))
1232 MakePathRelative(absoluteFilePath, dir, relativePath);
1240 if(SourceDirDialog(title, directory, null, sourceDir))
1242 if(eString_PathInsideOf(absolutePath, sourceDir))
1244 AddSourceDir(sourceDir);
1245 MakePathRelative(absoluteFilePath, sourceDir, relativePath);
1248 else if(MessageBox { type = yesNo, master = ide,
1249 contents = "You must provide a valid source directory in order to place a breakpoint in this file.\nWould you like to try again?",
1250 text = "Invalid Source Directory" }.Modal() == no)
1253 else if(MessageBox { type = yesNo, master = ide,
1254 contents = "You must provide a source directory in order to place a breakpoint in this file.\nWould you like to try again?",
1255 text = "No Source Directory Provided" }.Modal() == no)
1259 ide.workspace.bpCount++;
1260 bp = { line = lineNumber, type = user, enabled = true, level = -1 };
1261 ide.workspace.breakpoints.Add(bp);
1262 bp.absoluteFilePath = CopyString(absolutePath);
1263 bp.relativeFilePath = CopyString(relativePath);
1264 ide.breakpointsView.AddBreakpoint(bp);
1269 DebuggerState oldState = state;
1274 GdbDebugBreak(true);
1279 sentBreakInsert = true;
1280 GdbCommand(false, "-break-insert %s:%d", bp.relativeFilePath, bp.line);
1283 bp.inserted = (bp.bp && bp.bp.number != 0);
1284 ValidateBreakpoint(bp);
1288 if(oldState == running)
1289 GdbExecContinue(false);
1292 ide.workspace.Save();
1295 void UpdateRemovedBreakpoint(Breakpoint bp)
1297 if(targeted && bp.inserted)
1299 DebuggerState oldState = state;
1304 GdbDebugBreak(true);
1308 GdbCommand(false, "-break-delete %d", bp.bp.number);
1311 if(oldState == running)
1312 GdbExecContinue(false);
1318 void ParseFrame(Frame frame, char * string)
1321 Array<char *> frameTokens { minAllocSize = 50 };
1322 Array<char *> argsTokens { minAllocSize = 50 };
1323 Array<char *> argumentTokens { minAllocSize = 50 };
1324 DebugListItem item { };
1327 TokenizeList(string, ',', frameTokens);
1328 for(i = 0; i < frameTokens.count; i++)
1330 if(TokenizeListItem(frameTokens[i], item))
1332 StripQuotes(item.value, item.value);
1333 if(!strcmp(item.name, "level"))
1334 frame.level = atoi(item.value);
1335 else if(!strcmp(item.name, "addr"))
1336 frame.addr = CopyString(item.value);
1337 else if(!strcmp(item.name, "func"))
1338 frame.func = CopyString(item.value);
1339 else if(!strcmp(item.name, "args"))
1341 if(!strcmp(item.value, "[]"))
1342 frame.argsCount = 0;
1345 item.value = StripBrackets(item.value);
1346 TokenizeList(item.value, ',', argsTokens);
1347 for(j = 0; j < argsTokens.count; j++)
1349 argsTokens[j] = StripCurlies(argsTokens[j]);
1350 TokenizeList(argsTokens[j], ',', argumentTokens);
1351 for(k = 0; k < argumentTokens.count; k++)
1354 frame.args.Add(arg);
1355 if(TokenizeListItem(argumentTokens[k], item))
1357 if(!strcmp(item.name, "name"))
1359 StripQuotes(item.value, item.value);
1360 arg.name = CopyString(item.value);
1362 else if(!strcmp(item.name, "value"))
1364 StripQuotes(item.value, item.value);
1365 arg.value = CopyString(item.value);
1368 DebuggerProtocolUnknown("Unknown frame args item name", item.name);
1371 DebuggerProtocolUnknown("Bad frame args item", "");
1373 argumentTokens.RemoveAll();
1375 frame.argsCount = argsTokens.count;
1376 argsTokens.RemoveAll();
1379 else if(!strcmp(item.name, "from"))
1380 frame.from = item.value;
1381 else if(!strcmp(item.name, "file"))
1383 frame.file = item.value;
1384 frame.absoluteFile = ide.workspace.GetAbsolutePathFromRelative(frame.file);
1386 else if(!strcmp(item.name, "line"))
1387 frame.line = atoi(item.value);
1388 else if(!strcmp(item.name, "fullname"))
1390 // New GDB is giving us a full name... Any reason why we coudln't figure it out ourselves?
1393 DebuggerProtocolUnknown("Unknown frame member name", item.name);
1396 DebuggerProtocolUnknown("Bad frame", "");
1401 delete argumentTokens;
1405 void ShowDebuggerViews()
1407 ide.outputView.Show();
1408 ide.outputView.SelectTab(debug);
1409 ide.threadsView.Show();
1410 ide.callStackView.Show();
1411 ide.watchesView.Show();
1415 void HideDebuggerViews()
1417 ide.RepositionWindows(true);
1420 void ::GdbCommand(bool focus, char * format, ...)
1424 char string[MAX_F_STRING];
1427 va_start(args, format);
1428 vsprintf(string, format, args);
1432 ide.debugger.serialSemaphore.TryWait();
1435 #ifdef GDB_DEBUG_CONSOLE
1436 Log(string); Log("\n");
1438 #ifdef GDB_DEBUG_OUTPUT
1439 ide.outputView.gdbBox.Logf("cmd: %s\n", string);
1441 #ifdef GDB_DEBUG_GUI
1443 ide.gdbDialog.AddCommand(string);
1445 gdbHandle.Printf("%s\n", string);
1448 Process_ShowWindows(targetProcessId);
1451 ide.debugger.serialSemaphore.Wait();
1456 bool ValidateBreakpoint(Breakpoint bp)
1460 if(bp.bp.line != bp.line)
1465 ide.outputView.debugBox.Logf("WOULD HAVE -- Invalid breakpoint disabled: %s:%d\n", bp.relativeFilePath, bp.line);
1469 //GdbCommand(false, "-break-delete %d", bp.bp.number);
1470 //bp.inserted = false;
1472 //bp.enabled = false;
1477 ide.outputView.debugBox.Logf("Debugger Error: ValidateBreakpoint error\n");
1478 bp.line = bp.bp.line;
1485 static void GdbInsertInternalBreakpoint()
1489 //if(!breakpointsInserted)
1491 DirExpression objDir = ide.project.objDir;
1496 if(bp.type == internalMain)
1498 sentBreakInsert = true;
1499 GdbCommand(false, "-break-insert main");
1502 bp.inserted = (bp.bp && bp.bp.number != 0);
1504 #if defined(__WIN32__)
1505 else if(bp.type == internalWinMain)
1507 sentBreakInsert = true;
1508 GdbCommand(false, "-break-insert WinMain");
1511 bp.inserted = (bp.bp && bp.bp.number != 0);
1514 else if(bp.type == internalModulesLoaded)
1516 char path[MAX_LOCATION];
1517 char name[MAX_LOCATION];
1518 char fixedModuleName[MAX_FILENAME];
1521 bool moduleLoadBlock = false;
1523 ReplaceSpaces(fixedModuleName, ide.project.moduleName);
1524 sprintf(name, "%s.main.ec", fixedModuleName);
1525 strcpy(path, ide.workspace.projectDir);
1526 PathCatSlash(path, objDir.dir);
1527 PathCatSlash(path, name);
1528 f = FileOpen(path, read);
1531 for(lineNumber = 1; !f.Eof(); lineNumber++)
1533 if(f.GetLine(line, sizeof(line) - 1))
1535 bool moduleLoadLine;
1536 TrimLSpaces(line, line);
1537 moduleLoadLine = !strncmp(line, "eModule_Load", strlen("eModule_Load"));
1538 if(!moduleLoadBlock && moduleLoadLine)
1539 moduleLoadBlock = true;
1540 else if(moduleLoadBlock && !moduleLoadLine && strlen(line) > 0)
1546 char relative[MAX_LOCATION];
1547 bp.absoluteFilePath = CopyString(path);
1548 MakePathRelative(path, ide.workspace.projectDir, relative);
1549 delete bp.relativeFilePath;
1550 bp.relativeFilePath = CopyString(relative);
1551 bp.line = lineNumber;
1552 sentBreakInsert = true;
1553 GdbCommand(false, "-break-insert %s:%d", bp.relativeFilePath, lineNumber);
1556 bp.inserted = (bp.bp && bp.bp.number != 0);
1557 ValidateBreakpoint(bp);
1570 void GdbBreakpointsInsert()
1574 //if(!breakpointsInserted)
1576 //if(!ignoreBreakpoints)
1577 //breakpointsInserted = true;
1578 for(bp : ide.workspace.breakpoints)
1580 if(!bp.inserted && bp.type == user)
1582 if(!ignoreBreakpoints && bp.enabled)
1584 sentBreakInsert = true;
1585 GdbCommand(false, "-break-insert %s:%d", bp.relativeFilePath, bp.line);
1588 bp.inserted = (bp.bp && bp.bp.number != 0);
1590 ValidateBreakpoint(bp);
1596 printf("problem\n");
1598 bp.bp = GdbDataBreakpoint { };
1602 if(bpRunToCursor && !bpRunToCursor.inserted)
1604 sentBreakInsert = true;
1605 GdbCommand(false, "-break-insert %s:%d", bpRunToCursor.relativeFilePath, bpRunToCursor.line);
1606 bpRunToCursor.bp = bpItem;
1608 bpRunToCursor.inserted = (bpRunToCursor.bp && bpRunToCursor.bp.number != 0);
1609 ValidateBreakpoint(bpRunToCursor);
1615 void GdbBreakpointsDelete(bool deleteRunToCursor)
1617 //breakpointsInserted = false;
1620 for(bp : ide.workspace.breakpoints)
1623 GdbCommand(false, "-break-delete %d", bp.bp.number);
1624 bp.inserted = false;
1626 //check here (reply form -break-delete, returns bpitem?)
1629 if(deleteRunToCursor && bpRunToCursor)
1631 GdbCommand(false, "-break-delete %d", bpRunToCursor.bp.number);
1632 bpRunToCursor.inserted = false;
1633 bpRunToCursor.bp = bpItem;
1634 //check here (reply form -break-delete, returns bpitem?)
1643 stackFrames.Free(Frame::Free);
1644 GdbCommand(false, "-stack-info-depth");
1646 GdbCommand(false, "-stack-info-depth 192");
1647 if(frameCount && frameCount <= 192)
1648 GdbCommand(false, "-stack-list-frames 0 191");
1651 GdbCommand(false, "-stack-list-frames 0 95");
1652 GdbCommand(false, "-stack-list-frames %d %d", Max(frameCount - 96, 96), frameCount - 1);
1654 GdbCommand(false, "");
1661 char escaped[MAX_LOCATION];
1662 strescpy(escaped, targetFile);
1663 GdbCommand(false, "file \"%s\"", escaped); //GDB/MI Missing Implementation -symbol-file, -target-attach
1668 for(prj : ide.workspace.projects)
1670 if(prj == ide.workspace.projects.firstIterator.data)
1673 //PrintLn("THIS: ", (String)prj.topNode.path);
1674 GdbCommand(false, "-environment-directory \"%s\"", prj.topNode.path);
1675 //GdbCommand(false, ""); // why this empty GDB command
1678 for(dir : ide.workspace.sourceDirs)
1680 GdbCommand(false, "-environment-directory \"%s\"", dir);
1681 //GdbCommand(false, ""); // why this empty GDB command
1683 GdbInsertInternalBreakpoint();
1689 void GdbTargetRelease()
1693 GdbBreakpointsDelete(true);
1694 GdbCommand(false, "file"); //GDB/MI Missing Implementation -target-detach
1700 void GdbDebugBreak(bool internal)
1705 breakType = DebuggerAction::internal;
1709 ide.DebugUpdateMenus(running, true);
1713 if(Process_Break(targetProcessId)) //GdbCommand(false, "-exec-interrupt");
1714 serialSemaphore.Wait();
1718 targetProcessId = 0;
1719 ide.DebugUpdateMenus(loaded, false);
1724 ide.outputView.debugBox.Logf("Debugger Error: GdbDebugBreak with not target id should never happen\n");
1731 ShowDebuggerViews();
1732 GdbCommand(true, "-exec-run");
1735 void GdbExecContinue(bool focus)
1738 GdbCommand(focus, "-exec-continue");
1744 GdbCommand(true, "-exec-next");
1750 GdbCommand(true, "-exec-step");
1753 void GdbExecFinish()
1756 GdbCommand(true, "-exec-finish");
1759 void GdbExecCommon()
1761 ClearBreakDisplay();
1762 GdbBreakpointsInsert();
1765 #ifdef GDB_DEBUG_GUI
1766 void SendGDBCommand(char * command)
1768 DebuggerState oldState = state;
1773 GdbDebugBreak(true);
1776 GdbCommand(false, command);
1779 if(oldState == running)
1780 GdbExecContinue(false);
1784 void ClearBreakDisplay()
1787 activeFrameLevel = -1;
1798 stackFrames.Free(Frame::Free);
1799 WatchesCodeEditorLinkRelease();
1800 ide.callStackView.Clear();
1801 ide.threadsView.Clear();
1808 GdbCommand(false, "-interpreter-exec console \"kill\""); // should use -exec-abort -- GDB/MI implementation incomplete
1815 char oldDirectory[MAX_LOCATION];
1816 char tempPath[MAX_LOCATION];
1817 char command[MAX_LOCATION];
1818 char oldPath[MAX_LOCATION * 65];
1819 Project project = ide.project;
1820 DirExpression targetDirExp = project.targetDir;
1822 GetEnvironment("PATH", oldPath, sizeof(oldPath));
1824 prjConfig = project.config;
1828 sentBreakInsert = false;
1832 //breakpointsInserted = false;
1834 ide.outputView.ShowClearSelectTab(debug);
1835 ide.outputView.debugBox.Logf("Starting debug mode\n");
1837 #ifdef GDB_DEBUG_CONSOLE
1838 Log("Starting GDB"); Log("\n");
1840 #ifdef GDB_DEBUG_OUTPUT
1841 ide.outputView.gdbBox.Logf("run: Starting GDB\n");
1844 strcpy(tempPath, ide.workspace.projectDir);
1845 PathCatSlash(tempPath, targetDirExp.dir);
1847 targetDir = CopyString(tempPath);
1848 project.CatTargetFileName(tempPath);
1850 targetFile = CopyString(tempPath);
1852 GetWorkingDir(oldDirectory, MAX_LOCATION);
1853 if(ide.workspace.debugDir && ide.workspace.debugDir[0])
1855 char temp[MAX_LOCATION];
1856 strcpy(temp, ide.workspace.projectDir);
1857 PathCatSlash(temp, ide.workspace.debugDir);
1858 ChangeWorkingDir(temp);
1861 ChangeWorkingDir(ide.workspace.projectDir);
1865 sprintf(command, "gdb -n -silent --interpreter=mi2"); //-async //\"%s\"
1867 gdbHandle = DualPipeOpen(PipeOpenMode { output = 1, error = 2, input = 1 }, command);
1870 ide.outputView.debugBox.Logf("Debugger Fatal Error: Couldn't start GDB\n");
1878 gdbProcessId = gdbHandle.GetProcessID();
1881 ide.outputView.debugBox.Logf("Debugger Fatal Error: Couldn't get GDB process ID\n");
1887 serialSemaphore.Wait();
1892 //state = terminated;
1893 //ide.DebugUpdateMenus(loaded, false);
1899 #if defined(__unix__)
1901 CreateTemporaryDir(progFifoDir, "ecereide");
1902 strcpy(progFifoPath, progFifoDir);
1903 PathCat(progFifoPath, "ideprogfifo");
1904 if(!mkfifo(progFifoPath, 0600))
1906 //fileCreated = true;
1911 ide.outputView.debugBox.Logf("err: Unable to create FIFO %s\n", progFifoPath);
1916 progThread.terminate = false;
1917 progThread.Create();
1920 #if defined(__WIN32__)
1921 GdbCommand(false, "-gdb-set new-console on");
1924 GdbCommand(false, "-gdb-set verbose off");
1925 //GdbCommand(false, "-gdb-set exec-done-display on");
1926 GdbCommand(false, "-gdb-set step-mode off");
1927 GdbCommand(false, "-gdb-set unwindonsignal on");
1928 //GdbCommand(false, "-gdb-set shell on");
1929 GdbCommand(false, "set print elements 992");
1930 GdbCommand(false, "-gdb-set backtrace limit 100000");
1932 #if defined(__unix__)
1933 GdbCommand(false, "-inferior-tty-set %s", progFifoPath);
1936 GdbCommand(false, "-gdb-set args %s", ide.workspace.commandLineArgs ? ide.workspace.commandLineArgs : "");
1941 ChangeWorkingDir(oldDirectory);
1942 SetEnvironment("PATH", oldPath);
1946 delete targetDirExp;
1952 if(gdbHandle && gdbProcessId)
1954 GdbCommand(false, "-gdb-exit");
1973 for(bp : ide.workspace.breakpoints)
1974 bp.inserted = false;
1976 bp.inserted = false;
1978 bpRunToCursor.inserted = false;
1980 ide.outputView.debugBox.Logf("Debugging stopped\n");
1981 ClearBreakDisplay();
1982 ide.DebugUpdateMenus(loaded, false);
1985 #if defined(__unix__)
1986 if(FileExists(progFifoPath)) //fileCreated)
1988 progThread.terminate = true;
1991 fifoFile.CloseInput();
1997 DeleteFile(progFifoPath);
1998 progFifoPath[0] = '\0';
2004 void WatchesCodeEditorLinkInit()
2007 char tempPath[MAX_LOCATION];
2008 char path[MAX_LOCATION];
2010 //void MakeFilePathProjectRelative(char * path, char * relativePath)
2011 if(!ide.projectView.GetRelativePath(activeFrame.file, tempPath))
2012 strcpy(tempPath, activeFrame.file);
2014 strcpy(path, ide.workspace.projectDir);
2015 PathCat(path, tempPath);
2016 codeEditor = (CodeEditor)ide.OpenFile(path, Normal, false, null, no);
2019 for(srcDir : ide.workspace.sourceDirs)
2021 strcpy(path, srcDir);
2022 PathCat(path, tempPath);
2023 codeEditor = (CodeEditor)ide.OpenFile(path, Normal, false, null, no);
2024 if(codeEditor) break;
2029 if(activeFrame && !activeFrame.absoluteFile && activeFrame.file)
2030 activeFrame.absoluteFile = ide.workspace.GetAbsolutePathFromRelative(activeFrame.file);
2031 if(!activeFrame || !activeFrame.absoluteFile)
2034 codeEditor = (CodeEditor)ide.OpenFile(activeFrame.absoluteFile, normal, false, null, no, normal);
2037 codeEditor.inUseDebug = true;
2040 //watchesInit = true;
2043 void WatchesCodeEditorLinkRelease()
2049 codeEditor.inUseDebug = false;
2050 if(!codeEditor.visible)
2051 codeEditor.Destroy(0);
2057 bool ResolveWatch(Watch wh)
2059 bool result = false;
2072 char watchmsg[MAX_F_STRING];
2073 if(state == stopped && !codeEditor)
2074 wh.value = CopyString("No source file found for selected frame");
2075 //if(codeEditor && state == stopped || state != stopped)
2078 Module backupPrivateModule;
2079 Context backupContext;
2080 Class backupThisClass;
2084 backupPrivateModule = GetPrivateModule();
2085 backupContext = GetCurrentContext();
2086 backupThisClass = GetThisClass();
2089 SetPrivateModule(codeEditor.privateModule);
2090 SetCurrentContext(codeEditor.globalContext);
2091 SetTopContext(codeEditor.globalContext);
2092 SetGlobalContext(codeEditor.globalContext);
2093 SetGlobalData(&codeEditor.globalData);
2096 exp = ParseExpressionString(wh.expression);
2098 if(exp && !parseError)
2100 if(GetPrivateModule())
2103 DebugFindCtxTree(codeEditor.ast, activeFrame.line, 0);
2104 ProcessExpressionType(exp);
2106 wh.type = exp.expType;
2109 DebugComputeExpression(exp);
2111 /*if(exp.hasAddress)
2113 char temp[MAX_F_STRING];
2114 sprintf(temp, "0x%x", exp.address);
2115 wh.address = CopyString(temp);
2116 // wh.address = CopyStringf("0x%x", exp.address);
2121 Type dataType = exp.expType;
2124 char temp[MAX_F_STRING];
2125 switch(dataType.kind)
2128 sprintf(temp, "%i", exp.val.c);
2131 sprintf(temp, "%i", exp.val.s);
2136 sprintf(temp, "%i", exp.val.i);
2139 sprintf(temp, "%i", exp.val.i64);
2142 sprintf(temp, "%i", exp.val.p);
2147 long v = (long)exp.val.f;
2148 sprintf(temp, "%i", v);
2153 long v = (long)exp.val.d;
2154 sprintf(temp, "%i", v);
2159 wh.intVal = CopyString(temp);
2160 switch(dataType.kind)
2163 sprintf(temp, "0x%x", exp.val.c);
2166 sprintf(temp, "0x%x", exp.val.s);
2170 sprintf(temp, "0x%x", exp.val.i);
2173 sprintf(temp, "0x%x", exp.val.i64);
2176 sprintf(temp, "0x%x", exp.val.i64);
2179 sprintf(temp, "0x%x", exp.val.p);
2184 long v = (long)exp.val.f;
2185 sprintf(temp, "0x%x", v);
2190 long v = (long)exp.val.d;
2191 sprintf(temp, "0x%x", v);
2196 wh.hexVal = CopyString(temp);
2197 switch(dataType.kind)
2200 sprintf(temp, "0o%o", exp.val.c);
2203 sprintf(temp, "0o%o", exp.val.s);
2207 sprintf(temp, "0o%o", exp.val.i);
2210 sprintf(temp, "0o%o", exp.val.i64);
2213 sprintf(temp, "0o%o", exp.val.i64);
2216 sprintf(temp, "0o%o", exp.val.p);
2221 long v = (long)exp.val.f;
2222 sprintf(temp, "0o%o", v);
2227 long v = (long)exp.val.d;
2228 sprintf(temp, "0o%o", v);
2233 wh.octVal = CopyString(temp);
2236 // WHATS THIS HERE ?
2237 if(exp.type == constantExp && exp.constant)
2238 wh.constant = CopyString(exp.constant);
2244 case symbolErrorExp:
2245 sprintf(watchmsg, "Symbol \"%s\" not found", exp.identifier.string);
2247 case structMemberSymbolErrorExp:
2248 // todo get info as in next case (ExpClassMemberSymbolError)
2249 sprintf(watchmsg, "Error: Struct member not found for \"%s\"", wh.expression);
2251 case classMemberSymbolErrorExp:
2254 Expression memberExp = exp.member.exp;
2255 Identifier memberID = exp.member.member;
2256 Type type = memberExp.expType;
2259 _class = (memberID && memberID.classSym) ? memberID.classSym.registered : ((type.kind == classType && type._class) ? type._class.registered : null);
2262 char string[256] = "";
2264 PrintType(type, string, false, true);
2265 classSym = FindClass(string);
2266 _class = classSym ? classSym.registered : null;
2269 sprintf(watchmsg, "Member \"%s\" not found in class \"%s\"", memberID ? memberID.string : "", _class.name);
2271 sprintf(watchmsg, "Member \"%s\" not found in unregistered class? (Should never get this message)", memberID ? memberID.string : "");
2274 sprintf(watchmsg, "Member \"%s\" not found in no type? (Should never get this message)", memberID ? memberID.string : "");
2277 case memoryErrorExp:
2278 sprintf(watchmsg, "Memory can't be read at %s", (exp.type == constantExp) ? exp.constant : null);
2280 case dereferenceErrorExp:
2281 sprintf(watchmsg, "Dereference failure for \"%s\"", wh.expression);
2283 case unknownErrorExp:
2284 sprintf(watchmsg, "Unknown error for \"%s\"", wh.expression);
2286 case noDebuggerErrorExp:
2287 sprintf(watchmsg, "Debugger required for symbol evaluation in \"%s\"", wh.expression);
2289 case debugStateErrorExp:
2290 sprintf(watchmsg, "Incorrect debugger state for symbol evaluation in \"%s\"", wh.expression);
2293 sprintf(watchmsg, "Null type for \"%s\"", wh.expression);
2297 // Temporary Code for displaying Strings
2298 if((exp.expType && ((exp.expType.kind == pointerType ||
2299 exp.expType.kind == arrayType) && exp.expType.type.kind == charType)) ||
2300 (wh.type && wh.type.kind == classType && wh.type._class &&
2301 wh.type._class.registered && wh.type._class.registered.type == normalClass &&
2302 !strcmp(wh.type._class.registered.name, "String")))
2305 if(exp.expType.kind != arrayType || exp.hasAddress)
2311 //char temp[MAX_F_STRING * 32];
2313 ExpressionType evalError = dummyExp;
2314 /*if(exp.expType.kind == arrayType)
2315 sprintf(temp, "(char*)0x%x", exp.address);
2317 sprintf(temp, "(char*)%s", exp.constant);*/
2319 //evaluation = Debugger::EvaluateExpression(temp, &evalError);
2320 address = strtoul(exp.constant, null, 0);
2321 //printf("%x\n", address);
2322 sprintf(value, "0x%08x ", address);
2325 strcat(value, "Null string");
2329 len = strlen(value);
2331 while(!string && size > 2)
2333 string = GdbReadMemory(address, size);
2336 if(string && string[0])
2339 if(UTF8Validate(string))
2344 for(c = 0; (ch = string[c]) && c<4096; c++)
2347 value[len++] = '\0';
2352 ISO8859_1toUTF8(string, value + len, 4096 - len - 30);
2353 strcat(value, ") (ISO8859-1)");
2360 strcat(value, "Empty string");
2364 strcat(value, "Couldn't read memory");
2366 wh.value = CopyString(value);
2369 else if(wh.type && wh.type.kind == classType && wh.type._class &&
2370 wh.type._class.registered && wh.type._class.registered.type == enumClass)
2372 uint64 value = strtoul(exp.constant, null, 0);
2373 Class enumClass = eSystem_FindClass(GetPrivateModule(), wh.type._class.registered.name);
2374 EnumClassData enumeration = (EnumClassData)enumClass.data;
2376 for(item = enumeration.values.first; item; item = item.next)
2377 if((int)item.data == value)
2380 wh.value = CopyString(item.name);
2382 wh.value = CopyString("Invalid Enum Value");
2383 result = (bool)atoi(exp.constant);
2385 else if(wh.type && (wh.type.kind == charType || (wh.type.kind == classType && wh.type._class &&
2386 wh.type._class.registered && !strcmp(wh.type._class.registered.fullName, "ecere::com::unichar"))) )
2393 if(exp.constant[0] == '\'')
2395 if((int)((byte *)exp.constant)[1] > 127)
2398 value = UTF8GetChar(exp.constant + 1, &nb);
2399 if(nb < 2) value = exp.constant[1];
2400 signedValue = value;
2404 signedValue = exp.constant[1];
2406 // Precomp Syntax error with boot strap here:
2407 byte b = (byte)(char)signedValue;
2408 value = (unichar) b;
2414 if(wh.type.kind == charType && wh.type.isSigned)
2416 signedValue = (int)(char)strtol(exp.constant, null, 0);
2418 // Precomp Syntax error with boot strap here:
2419 byte b = (byte)(char)signedValue;
2420 value = (unichar) b;
2425 value = strtoul(exp.constant, null, 0);
2426 signedValue = (int)value;
2430 UTF32toUTF8Len(&value, 1, charString, 5);
2432 sprintf(string, "\'\\0' (0)");
2433 else if(value == '\t')
2434 sprintf(string, "\'\\t' (%d)", value);
2435 else if(value == '\n')
2436 sprintf(string, "\'\\n' (%d)", value);
2437 else if(value == '\r')
2438 sprintf(string, "\'\\r' (%d)", value);
2439 else if(wh.type.kind == charType && wh.type.isSigned)
2440 sprintf(string, "\'%s\' (%d)", charString, signedValue);
2441 else if(value > 256 || wh.type.kind != charType)
2443 if(value > 0x10FFFF || !GetCharCategory(value))
2444 sprintf(string, "Invalid Unicode Keypoint (0x%08X)", value);
2446 sprintf(string, "\'%s\' (U+%04X)", charString, value);
2449 sprintf(string, "\'%s\' (%d)", charString, value);
2451 wh.value = CopyString(string);
2456 wh.value = CopyString(exp.constant);
2457 result = (bool)atoi(exp.constant);
2463 wh.value = PrintHexUInt(exp.address);
2464 result = (bool)exp.address;
2468 char tempString[256];
2469 sprintf(watchmsg, "Evaluation failed for \"%s\" of type \"%s\"", wh.expression,
2470 exp.type.OnGetString(tempString, null, null));
2476 sprintf(watchmsg, "Invalid expression: \"%s\"", wh.expression);
2477 if(exp) FreeExpression(exp);
2480 SetPrivateModule(backupPrivateModule);
2481 SetCurrentContext(backupContext);
2482 SetTopContext(backupContext);
2483 SetGlobalContext(backupContext);
2484 SetThisClass(backupThisClass);
2487 // wh.value = CopyString("No source file found for selected frame");
2490 wh.value = CopyString(watchmsg);
2492 ide.watchesView.UpdateWatch(wh);
2496 void EvaluateWatches()
2498 for(wh : ide.workspace.watches)
2502 char * ::GdbEvaluateExpression(char * expression)
2506 GdbCommand(false, "-data-evaluate-expression \"%s\"", expression);
2508 ide.outputView.debugBox.Logf("Debugger Error: GdbEvaluateExpression\n");
2512 // to be removed... use GdbReadMemory that returns a byte array instead
2513 char * ::GdbReadMemoryString(uint address, int size, char format, int rows, int cols)
2517 GdbCommand(false, "-data-read-memory 0x%08x %c, %d, %d, %d", address, format, size, rows, cols);
2519 ide.outputView.debugBox.Logf("Debugger Error: GdbReadMemoryString\n");
2523 byte * ::GdbReadMemory(uint address, int bytes)
2527 GdbCommand(false, "-data-read-memory 0x%08x %c, 1, 1, %d", address, 'u', bytes);
2529 ide.outputView.debugBox.Logf("Debugger Error: GdbReadMemory\n");
2530 else if(eval.result && strcmp(eval.result, "N/A"))
2532 byte * result = new byte[bytes];
2533 byte * string = eval.result;
2537 result[c++] = (byte)strtol(string, &string, 10);
2553 void EventHit(GdbDataStop stopItem)
2555 bool conditionMet = true;
2556 Breakpoint bp = bpHit;
2558 if(!bp && bpRunToCursor)
2562 GdbCommand(false, "-break-delete %d", bp.bp.number);
2567 if(bp.type == user && bp.line != stopItem.frame.line)
2569 bp.line = stopItem.frame.line;
2570 ide.breakpointsView.UpdateBreakpoint(bp.row);
2571 ide.workspace.Save();
2577 case internalWinMain:
2578 GdbBreakpointsInsert();
2579 if(userBreakOnInternBreak)
2581 userBreakOnInternBreak = false;
2582 // Why was SelectFrame missing here?
2583 SelectFrame(activeFrameLevel);
2584 GoToStackFrameLine(activeFrameLevel, true);
2585 ide.DebugUpdateMenus(stopped, false);
2590 GdbExecContinue(false);
2592 case internalModulesLoaded:
2594 GdbBreakpointsInsert();
2595 GdbExecContinue(false);
2600 conditionMet = ResolveWatch(bp.condition);
2601 if(conditionMet && (bp.level == -1 || bp.level == frameCount))
2604 if(bp.hits > bp.ignore)
2606 ignoreBreakpoints = false;
2607 // Why was SelectFrame missing here?
2608 SelectFrame(activeFrameLevel);
2609 GoToStackFrameLine(activeFrameLevel, true);
2610 ide.DebugUpdateMenus(stopped, false);
2613 if(bp.type == BreakpointType::runToCursor)
2615 delete bpRunToCursor;
2616 bpRunToCursor = null;
2622 ide.breakpointsView.UpdateBreakpoint(bp.row);*/
2623 GdbExecContinue(false);
2627 GdbExecContinue(false);
2632 ide.outputView.debugBox.Logf("Debugger Error: Breakpoint hit could not match breakpoint instance\n");
2635 void GdbThreadExit()
2637 if(state != terminated)
2640 targetProcessId = 0;
2641 ClearBreakDisplay();
2642 ide.DebugUpdateMenus(loaded, false);
2646 serialSemaphore.Release();
2651 ide.outputView.debugBox.Logf("Debugger Fatal Error: GDB lost\n");
2652 ide.outputView.debugBox.Logf("Debugging stopped\n");
2655 //state = terminated;
2659 void GdbThreadMain(char * output)
2662 Array<char *> outTokens { minAllocSize = 50 };
2663 Array<char *> subTokens { minAllocSize = 50 };
2664 DebugListItem item { };
2665 DebugListItem item2 { };
2666 bool setWaitingForPID = false;
2668 #if defined(GDB_DEBUG_CONSOLE) || defined(GDB_DEBUG_GUI)
2669 #ifdef GDB_DEBUG_CONSOLE
2670 Log(output); Log("\n");
2672 #ifdef GDB_DEBUG_OUTPUT
2674 int len = strlen(output);
2682 for(c = 0; c < len / 1024; c++)
2684 strncpy(tmp, start, 1024);
2685 ide.outputView.gdbBox.Logf("out: %s\n", tmp);
2688 ide.outputView.gdbBox.Logf("out: %s\n", start);
2692 ide.outputView.gdbBox.Logf("out: %s\n", output);
2696 #ifdef GDB_DEBUG_CONSOLE
2697 strcpy(lastGdbOutput, output);
2699 #ifdef GDB_DEBUG_GUI
2700 if(ide.gdbDialog) ide.gdbDialog.AddOutput(output);
2707 if(strstr(output, "No debugging symbols found") || strstr(output, "(no debugging symbols found)"))
2710 ide.outputView.debugBox.Logf("Target doesn't contain debug information!\n");
2716 if(TokenizeList(output, ',', outTokens) && !strcmp(outTokens[0], "^done"))
2718 //if(outTokens.count == 1)
2724 targetProcessId = 0;
2725 if(outTokens.count > 1 && TokenizeListItem(outTokens[1], item))
2727 if(!strcmp(item.name, "reason"))
2729 char * reason = item.value;
2730 StripQuotes(reason, reason);
2731 if(!strcmp(reason, "exited-normally") || !strcmp(reason, "exited") || !strcmp(reason, "exited-signalled"))
2734 if(outTokens.count > 2 && TokenizeListItem(outTokens[2], item2))
2736 StripQuotes(item2.value, item2.value);
2737 if(!strcmp(item2.name, "exit-code"))
2738 exitCode = item2.value;
2744 HandleExit(reason, exitCode);
2748 DebuggerProtocolUnknown("Unknown kill reply", item.name);
2751 HandleExit(null, null);
2754 if(outTokens.count > 1 && TokenizeListItem(outTokens[1], item))
2756 if(!strcmp(item.name, "bkpt"))
2758 sentBreakInsert = false;
2761 printf("problem\n");
2763 bpItem = GdbDataBreakpoint { };
2764 item.value = StripCurlies(item.value);
2765 TokenizeList(item.value, ',', subTokens);
2766 for(i = 0; i < subTokens.count; i++)
2768 if(TokenizeListItem(subTokens[i], item))
2770 StripQuotes(item.value, item.value);
2771 if(!strcmp(item.name, "number"))
2772 bpItem.number = atoi(item.value);
2773 else if(!strcmp(item.name, "type"))
2774 bpItem.type = CopyString(item.value);
2775 else if(!strcmp(item.name, "disp"))
2776 bpItem.disp = CopyString(item.value);
2777 else if(!strcmp(item.name, "enabled"))
2778 bpItem.enabled = (!strcmpi(item.value, "y"));
2779 else if(!strcmp(item.name, "addr"))
2780 bpItem.addr = CopyString(item.value);
2781 else if(!strcmp(item.name, "func"))
2782 bpItem.func = CopyString(item.value);
2783 else if(!strcmp(item.name, "file"))
2784 bpItem.file = item.value;
2785 else if(!strcmp(item.name, "line"))
2786 bpItem.line = atoi(item.value);
2787 else if(!strcmp(item.name, "at"))
2788 bpItem.at = CopyString(item.value);
2789 else if(!strcmp(item.name, "times"))
2790 bpItem.times = atoi(item.value);
2793 //breakType = bpValidation;
2794 //app.SignalEvent();
2795 subTokens.RemoveAll();
2797 else if(!strcmp(item.name, "BreakpointTable"))
2798 ide.outputView.debugBox.Logf("Debugger Error: Command reply BreakpointTable not handled\n");
2799 else if(!strcmp(item.name, "depth"))
2801 StripQuotes(item.value, item.value);
2802 frameCount = atoi(item.value);
2804 stackFrames.Free(Frame::Free);
2806 else if(!strcmp(item.name, "stack"))
2809 if(stackFrames.count)
2810 ide.callStackView.Logf("...\n");
2813 item.value = StripBrackets(item.value);
2814 TokenizeList(item.value, ',', subTokens);
2815 for(i = 0; i < subTokens.count; i++)
2817 if(TokenizeListItem(subTokens[i], item))
2819 if(!strcmp(item.name, "frame"))
2822 stackFrames.Add(frame);
2823 item.value = StripCurlies(item.value);
2824 ParseFrame(frame, item.value);
2825 if(frame.file && frame.from)
2826 DebuggerProtocolUnknown("Unexpected frame file and from members present", "");
2830 if(activeFrameLevel == -1)
2832 if(ide.projectView.IsModuleInProject(frame.file));
2834 if(frame.level != 0)
2836 //stopItem.frame = frame;
2837 breakType = selectFrame;
2840 activeFrame = frame;
2841 activeFrameLevel = frame.level;
2844 ide.callStackView.Logf("%3d ", frame.level);
2845 if(!strncmp(frame.func, "__ecereMethod_", strlen("__ecereMethod_")))
2846 ide.callStackView.Logf("%s Method, %s:%d\n", &frame.func[strlen("__ecereMethod_")], (s = CopySystemPath(frame.file)), frame.line);
2847 else if(!strncmp(frame.func, "__ecereProp_", strlen("__ecereProp_")))
2848 ide.callStackView.Logf("%s Property, %s:%d\n", &frame.func[strlen("__ecereProp_")], (s = CopySystemPath(frame.file)), frame.line);
2849 else if(!strncmp(frame.func, "__ecereConstructor_", strlen("__ecereConstructor_")))
2850 ide.callStackView.Logf("%s Constructor, %s:%d\n", &frame.func[strlen("__ecereConstructor_")], (s = CopySystemPath(frame.file)), frame.line);
2851 else if(!strncmp(frame.func, "__ecereDestructor_", strlen("__ecereDestructor_")))
2852 ide.callStackView.Logf("%s Destructor, %s:%d\n", &frame.func[strlen("__ecereDestructor_")], (s = CopySystemPath(frame.file)), frame.line);
2854 ide.callStackView.Logf("%s Function, %s:%d\n", frame.func, (s = CopySystemPath(frame.file)), frame.line);
2859 ide.callStackView.Logf("%3d ", frame.level);
2864 ide.callStackView.Logf("inside %s, %s\n", frame.func, (s = CopySystemPath(frame.from)));
2868 ide.callStackView.Logf("%s\n", frame.func);
2870 ide.callStackView.Logf("unknown source\n");
2874 DebuggerProtocolUnknown("Unknown stack content", item.name);
2877 if(activeFrameLevel == -1)
2879 activeFrameLevel = 0;
2880 activeFrame = stackFrames.first;
2882 ide.callStackView.Home();
2884 subTokens.RemoveAll();
2886 /*else if(!strcmp(item.name, "frame"))
2889 item.value = StripCurlies(item.value);
2890 ParseFrame(&frame, item.value);
2892 else if(!strcmp(item.name, "thread-ids"))
2894 ide.threadsView.Clear();
2895 item.value = StripCurlies(item.value);
2896 TokenizeList(item.value, ',', subTokens);
2897 for(i = subTokens.count - 1; ; i--)
2899 if(TokenizeListItem(subTokens[i], item))
2901 if(!strcmp(item.name, "thread-id"))
2904 StripQuotes(item.value, item.value);
2905 value = atoi(item.value);
2906 ide.threadsView.Logf("%3d \n", value);
2909 DebuggerProtocolUnknown("Unknown threads content", item.name);
2914 ide.threadsView.Home();
2916 subTokens.RemoveAll();
2917 //if(!strcmp(outTokens[2], "number-of-threads"))
2919 else if(!strcmp(item.name, "new-thread-id"))
2921 StripQuotes(item.value, item.value);
2922 activeThread = atoi(item.value);
2924 else if(!strcmp(item.name, "value"))
2926 StripQuotes(item.value, item.value);
2927 eval.result = CopyString(item.value);
2928 eval.active = false;
2930 else if(!strcmp(item.name, "addr"))
2932 for(i = 2; i < outTokens.count; i++)
2934 if(TokenizeListItem(outTokens[i], item))
2936 if(!strcmp(item.name, "total-bytes"))
2938 StripQuotes(item.value, item.value);
2939 eval.bytes = atoi(item.value);
2941 else if(!strcmp(item.name, "next-row"))
2943 StripQuotes(item.value, item.value);
2944 eval.nextBlockAddress = strtoul(item.value, null, 0);
2946 else if(!strcmp(item.name, "memory"))
2950 //StripQuotes(item.value, item.value);
2951 item.value = StripBrackets(item.value);
2952 // this should be treated as a list...
2953 item.value = StripCurlies(item.value);
2954 TokenizeList(item.value, ',', subTokens);
2955 for(j = 0; j < subTokens.count; j++)
2957 if(TokenizeListItem(subTokens[j], item))
2959 if(!strcmp(item.name, "data"))
2961 item.value = StripBrackets(item.value);
2962 StripQuotes2(item.value, item.value);
2963 eval.result = CopyString(item.value);
2964 eval.active = false;
2968 subTokens.RemoveAll();
2973 else if(!strcmp(item.name, "source-path"))
2977 DebuggerProtocolUnknown("Unknown command reply", item.name);
2980 else if(!strcmp(outTokens[0], "^running"))
2982 waitingForPID = true;
2983 setWaitingForPID = true;
2985 else if(!strcmp(outTokens[0], "^exit"))
2988 ide.DebugUpdateMenus(loaded, false);
2989 // ide.outputView.debugBox.Logf("Exit\n");
2992 serialSemaphore.Release();
2994 else if(!strcmp(outTokens[0], "^error"))
2998 sentBreakInsert = false;
3001 printf("problem\n");
3003 bpItem = GdbDataBreakpoint { };
3006 if(outTokens.count > 1 && TokenizeListItem(outTokens[1], item))
3008 if(!strcmp(item.name, "msg"))
3010 StripQuotes(item.value, item.value);
3013 eval.active = false;
3015 if(strstr(item.value, "No symbol") && strstr(item.value, "in current context"))
3016 eval.error = symbolNotFound;
3017 else if(strstr(item.value, "Cannot access memory at address"))
3018 eval.error = memoryCantBeRead;
3020 eval.error = unknown;
3022 else if(!strcmp(item.value, "Previous frame inner to this frame (corrupt stack?)"))
3025 else if(!strncmp(item.value, "Cannot access memory at address", 31))
3028 else if(!strcmp(item.value, "Cannot find bounds of current function"))
3031 gdbHandle.Printf("-exec-continue\n");
3033 else if(!strcmp(item.value, "ptrace: No such process."))
3036 targetProcessId = 0;
3037 ide.DebugUpdateMenus(loaded, false);
3039 else if(!strcmp(item.value, "Function \\\"WinMain\\\" not defined."))
3042 else if(!strcmp(item.value, "You can't do that without a process to debug."))
3045 targetProcessId = 0;
3046 ide.DebugUpdateMenus(loaded, false);
3048 else if(strstr(item.value, "No such file or directory."))
3051 targetProcessId = 0;
3052 ide.DebugUpdateMenus(loaded, false);
3057 if(strlen(item.value) < MAX_F_STRING)
3060 ide.outputView.debugBox.Logf("GDB: %s\n", (s = CopyUnescapedString(item.value)));
3064 ide.outputView.debugBox.Logf("GDB: %s\n", item.value);
3070 DebuggerProtocolUnknown("Unknown error content", item.name);
3073 DebuggerProtocolUnknown("Unknown result-record", outTokens[0]);
3075 outTokens.RemoveAll();
3078 DebuggerProtocolUnknown("Unknown status-async-output", outTokens[0]);
3081 if(TokenizeList(output, ',', outTokens) && !strcmp(outTokens[0], "=thread-group-created")) //=thread-group-created,id="7611"
3083 else if(!strcmp(outTokens[0], "=thread-created")) //=thread-created,id="1",group-id="7611"
3085 else if(!strcmp(outTokens[0], "=library-loaded")) //=library-loaded,id="/lib/ld-linux.so.2",target-name="/lib/ld-linux.so.2",host-name="/lib/ld-linux.so.2",symbols-loaded="0"
3088 DebuggerProtocolUnknown("Unknown notify-async-output", outTokens[0]);
3089 outTokens.RemoveAll();
3093 if(TokenizeList(output, ',', outTokens))
3095 if(!strcmp(outTokens[0],"*running"))
3097 waitingForPID = true;
3098 setWaitingForPID = true;
3100 else if(!strcmp(outTokens[0], "*stopped"))
3104 if(outTokens.count > 1 && TokenizeListItem(outTokens[1], item))
3106 if(!strcmp(item.name, "reason"))
3108 char * reason = item.value;
3109 StripQuotes(reason, reason);
3110 if(!strcmp(reason, "exited-normally") || !strcmp(reason, "exited") || !strcmp(reason, "exited-signalled"))
3113 if(outTokens.count > 2 && TokenizeListItem(outTokens[2], item2))
3115 StripQuotes(item2.value, item2.value);
3116 if(!strcmp(item2.name, "exit-code"))
3117 exitCode = item2.value;
3123 HandleExit(reason, exitCode);
3125 else if(!strcmp(reason, "breakpoint-hit"))
3129 printf("problem\n");
3131 stopItem = GdbDataStop { };
3133 for(i = 2; i < outTokens.count; i++)
3135 TokenizeListItem(outTokens[i], item);
3136 StripQuotes(item.value, item.value);
3137 if(!strcmp(item.name, "bkptno"))
3138 stopItem.bkptno = atoi(item.value);
3139 else if(!strcmp(item.name, "thread-id"))
3140 stopItem.threadid = atoi(item.value);
3141 else if(!strcmp(item.name, "frame"))
3143 item.value = StripCurlies(item.value);
3144 ParseFrame(stopItem.frame, item.value);
3147 DebuggerProtocolUnknown("Unknown breakpoint hit item name", item.name);
3152 else if(!strcmp(reason, "end-stepping-range"))
3156 printf("problem\n");
3158 stopItem = GdbDataStop { };
3160 for(i = 2; i < outTokens.count; i++)
3162 TokenizeListItem(outTokens[i], item);
3163 StripQuotes(item.value, item.value);
3164 if(!strcmp(item.name, "thread-id"))
3165 stopItem.threadid = atoi(item.value);
3166 else if(!strcmp(item.name, "frame"))
3168 item.value = StripCurlies(item.value);
3169 ParseFrame(stopItem.frame, item.value);
3171 else if(!strcmp(item.name, "reason"))
3173 else if(!strcmp(item.name, "bkptno"))
3176 DebuggerProtocolUnknown("Unknown end of stepping range item name", item.name);
3180 ide.DebugUpdateMenus(stopped, false);
3183 else if(!strcmp(reason, "function-finished"))
3187 printf("problem\n");
3189 stopItem = GdbDataStop { };
3190 stopItem.reason = CopyString(reason);
3192 for(i = 2; i < outTokens.count; i++)
3194 TokenizeListItem(outTokens[i], item);
3195 StripQuotes(item.value, item.value);
3196 if(!strcmp(item.name, "thread-id"))
3197 stopItem.threadid = atoi(item.value);
3198 else if(!strcmp(item.name, "frame"))
3200 item.value = StripCurlies(item.value);
3201 ParseFrame(stopItem.frame, item.value);
3203 else if(!strcmp(item.name, "gdb-result-var"))
3204 stopItem.gdbResultVar = CopyString(item.value);
3205 else if(!strcmp(item.name, "return-value"))
3206 stopItem.returnValue = CopyString(item.value);
3208 DebuggerProtocolUnknown("Unknown function finished item name", item.name);
3211 event = functionEnd;
3212 ide.DebugUpdateMenus(stopped, false);
3215 else if(!strcmp(reason, "signal-received"))
3219 printf("problem\n");
3221 stopItem = GdbDataStop { };
3222 stopItem.reason = CopyString(reason);
3224 for(i = 2; i < outTokens.count; i++)
3226 TokenizeListItem(outTokens[i], item);
3227 StripQuotes(item.value, item.value);
3228 if(!strcmp(item.name, "signal-name"))
3229 stopItem.name = CopyString(item.value);
3230 else if(!strcmp(item.name, "signal-meaning"))
3231 stopItem.meaning = CopyString(item.value);
3232 else if(!strcmp(item.name, "thread-id"))
3233 stopItem.threadid = atoi(item.value);
3234 else if(!strcmp(item.name, "frame"))
3236 item.value = StripCurlies(item.value);
3237 ParseFrame(stopItem.frame, item.value);
3240 DebuggerProtocolUnknown("Unknown signal reveived item name", item.name);
3242 if(!strcmp(stopItem.name, "SIGTRAP"))
3253 ide.DebugUpdateMenus(stopped, false);
3261 ide.DebugUpdateMenus(stopped, false);
3265 else if(!strcmp(reason, "watchpoint-trigger"))
3266 DebuggerProtocolUnknown("Reason watchpoint trigger not handled", "");
3267 else if(!strcmp(reason, "read-watchpoint-trigger"))
3268 DebuggerProtocolUnknown("Reason read watchpoint trigger not handled", "");
3269 else if(!strcmp(reason, "access-watchpoint-trigger"))
3270 DebuggerProtocolUnknown("Reason access watchpoint trigger not handled", "");
3271 else if(!strcmp(reason, "watchpoint-scope"))
3272 DebuggerProtocolUnknown("Reason watchpoint scope not handled", "");
3273 else if(!strcmp(reason, "location-reached"))
3274 DebuggerProtocolUnknown("Reason location reached not handled", "");
3276 DebuggerProtocolUnknown("Unknown reason", reason);
3283 DebuggerProtocolUnknown("Unknown exec-async-output", outTokens[0]);
3284 outTokens.RemoveAll();
3287 if(!strcmpi(output, "(gdb) "))
3291 char exeFile[MAX_LOCATION];
3292 int oldProcessID = targetProcessId;
3293 GetLastDirectory(targetFile, exeFile);
3297 targetProcessId = Process_GetChildExeProcessId(gdbProcessId, exeFile);
3298 if(targetProcessId || gdbHandle.Peek()) break;
3305 ide.DebugUpdateMenus(running, false);
3308 else if(!oldProcessID)
3310 ide.outputView.debugBox.Logf("Debugger Error: No target process ID\n");
3311 // TO VERIFY: The rest of this block has not been thoroughly tested in this particular location
3312 gdbHandle.Printf("-gdb-exit\n");
3314 state = terminated; //loaded;
3319 for(bp : ide.workspace.breakpoints)
3320 bp.inserted = false;
3323 bp.inserted = false;
3325 bpRunToCursor.inserted = false;
3327 ide.outputView.debugBox.Logf("Debugging stopped\n");
3328 ClearBreakDisplay();
3329 ide.DebugUpdateMenus(loaded, false);
3332 #if defined(__unix__)
3333 if(FileExists(progFifoPath)) //fileCreated)
3335 progThread.terminate = true;
3338 fifoFile.CloseInput();
3345 DeleteFile(progFifoPath);
3346 progFifoPath[0] = '\0';
3353 serialSemaphore.Release();
3356 DebuggerProtocolUnknown("Unknown prompt", output);
3360 if(!strncmp(output, "&\"warning:", 10))
3363 content = strstr(output, "\"");
3364 StripQuotes(content, content);
3365 content = strstr(content, ":");
3371 ide.outputView.debugBox.LogRaw((s = CopyUnescapedString(content)));
3378 DebuggerProtocolUnknown("Unknown output", output);
3380 if(!setWaitingForPID)
3381 waitingForPID = false;
3382 setWaitingForPID = false;
3390 void RunToCursorPrepare(char * absoluteFilePath, char * relativeFilePath, int lineNumber)
3394 //bpRunToCursor.Free();
3395 bpRunToCursor = Breakpoint { };
3398 bpRunToCursor = Breakpoint { };
3400 if(absoluteFilePath)
3401 bpRunToCursor.absoluteFilePath = CopyString(absoluteFilePath);
3402 if(relativeFilePath)
3403 bpRunToCursor.relativeFilePath = CopyString(relativeFilePath);
3404 bpRunToCursor.line = lineNumber;
3405 bpRunToCursor.type = runToCursor;
3406 bpRunToCursor.enabled = true;
3407 bpRunToCursor.condition = null;
3408 bpRunToCursor.ignore = 0;
3409 bpRunToCursor.level = -1;
3412 ExpressionType ::DebugEvalExpTypeError(char * result)
3418 case symbolNotFound:
3419 return symbolErrorExp;
3420 case memoryCantBeRead:
3421 return memoryErrorExp;
3423 return unknownErrorExp;
3426 char * ::EvaluateExpression(char * expression, ExpressionType * error)
3429 if(ide.projectView && ide.debugger.state == stopped)
3431 result = GdbEvaluateExpression(expression);
3432 *error = DebugEvalExpTypeError(result);
3437 *error = noDebuggerErrorExp;
3442 char * ::ReadMemory(uint address, int size, char format, ExpressionType * error)
3445 char * result = GdbReadMemoryString(address, size, format, 1, 1);
3446 if(!result || !strcmp(result, "N/A"))
3447 *error = memoryErrorExp;
3449 *error = DebugEvalExpTypeError(result);
3454 class GdbThread : Thread
3460 static char output[4096];
3461 Array<char> dynamicBuffer { minAllocSize = 4096 };
3462 DualPipe oldGdbHandle = gdbHandle;
3463 incref oldGdbHandle;
3466 while(debugger.state != terminated && gdbHandle && !gdbHandle.Eof())
3470 result = gdbHandle.Read(output, 1, sizeof(output));
3471 if(debugger.state == terminated || !gdbHandle || gdbHandle.Eof())
3479 for(c = 0; c<result; c++)
3481 if(output[c] == '\n')
3483 int pos = dynamicBuffer.size;
3484 dynamicBuffer.size += c - start;
3485 memcpy(&dynamicBuffer[pos], output + start, c - start);
3486 if(dynamicBuffer.count && dynamicBuffer[dynamicBuffer.count - 1] != '\r')
3487 // COMMENTED OUT DUE TO ISSUE #135, FIXED
3488 //if(dynamicBuffer.array[dynamicBuffer.count - 1] != '\r')
3489 dynamicBuffer.size++;
3490 dynamicBuffer[dynamicBuffer.count - 1] = '\0';
3492 // printf("%s\n", dynamicBuffer.array);
3494 debugger.GdbThreadMain(&dynamicBuffer[0]);
3495 dynamicBuffer.size = 0;
3501 int pos = dynamicBuffer.size;
3502 dynamicBuffer.size += c - start;
3503 memcpy(&dynamicBuffer[pos], output + start, c - start);
3509 printf("Got end of file from GDB!\n");
3513 delete dynamicBuffer;
3514 //if(oldGdbHandle == gdbHandle)
3515 debugger.GdbThreadExit();
3516 delete oldGdbHandle;
3522 #if defined(__unix__)
3527 #include <sys/types.h>
3532 class ProgramThread : Thread
3538 bool fileCreated = false;
3540 static char output[1000];
3543 /*if(!mkfifo(progFifoPath, mask))
3550 ide.outputView.debugBox.Logf("err: Unable to create FIFO %s\n", progFifoPath);
3554 if(FileExists(progFifoPath)) //fileCreated)
3556 fifoFile = FileOpen(progFifoPath, read);
3560 ide.outputView.debugBox.Logf("err: Unable to open FIFO %s for read\n", progFifoPath);
3569 fd = fileno(fifoFile.input);
3571 //fcntl(fd, F_SETFL, fcntl(fd, F_GETFL) | O_NONBLOCK);
3575 while(!terminate && fifoFile && !fifoFile.Eof())
3578 struct timeval time;
3586 selectResult = select(fd + 1, &rs, null, null, &time);
3587 if(FD_ISSET(fd, &rs))
3589 int result = read(fd, output, sizeof(output)-1);
3590 if(!result || (result < 0 && errno != EAGAIN))
3594 output[result] = '\0';
3595 if(strcmp(output,"&\"warning: GDB: Failed to set controlling terminal: Invalid argument\\n\"\n"))
3598 ide.outputView.debugBox.Log(output);
3607 //fifoFile.CloseInput();
3610 ide.outputView.debugBox.Log("\n");
3614 if(FileExists(progFifoPath)) //fileCreated)
3616 DeleteFile(progFifoPath);
3617 progFifoPath[0] = '\0';
3625 class Argument : struct
3627 Argument prev, next;
3643 class Frame : struct
3652 property char * from { set { delete from; if(value) from = CopyUnescapedUnixPath(value); } }
3654 property char * file { set { delete file; if(value) file = CopyUnescapedUnixPath(value); } }
3655 char * absoluteFile;
3664 delete absoluteFile;
3665 args.Free(Argument::Free);
3674 class GdbDataStop : struct
3691 char * gdbResultVar;
3701 if(!strcmp(reason, "signal-received"))
3706 else if(!strcmp(reason, "function-finished"))
3708 delete gdbResultVar;
3713 if(frame) frame.Free();
3722 class GdbDataBreakpoint : struct
3731 property char * file { set { delete file; if(value) file = CopyUnescapedUnixPath(value); } }
3746 ~GdbDataBreakpoint()
3752 class Breakpoint : struct
3756 char * relativeFilePath;
3757 char * absoluteFilePath;
3765 BreakpointType type;
3768 GdbDataBreakpoint bp;
3770 char * LocationToString()
3772 char location[MAX_LOCATION+20];
3773 sprintf(location, "%s:%d", relativeFilePath, line);
3774 #if defined(__WIN32__)
3775 ChangeCh(location, '/', '\\');
3777 return CopyString(location);
3782 if(relativeFilePath && relativeFilePath[0])
3784 f.Printf(" * %d,%d,%d,%d,%s\n", enabled ? 1 : 0, ignore, level, line, relativeFilePath);
3786 f.Printf(" ~ %s\n", condition.expression);
3795 delete relativeFilePath;
3796 delete absoluteFilePath;
3806 class Watch : struct
3817 f.Printf(" ~ %s\n", expression);
3841 class DebugListItem : struct
3847 struct DebugEvaluationData
3852 uint nextBlockAddress;
3854 DebuggerEvaluationError error;
3857 class CodeLocation : struct
3860 char * absoluteFile;
3863 CodeLocation ::ParseCodeLocation(char * location)
3867 char * colon = null;
3869 char loc[MAX_LOCATION];
3870 strcpy(loc, location);
3871 for(temp = loc; temp = strstr(temp, ":"); temp++)
3879 int line = atoi(colon);
3882 CodeLocation codloc { line = line };
3883 codloc.file = CopyString(loc);
3884 codloc.absoluteFile = ide.workspace.GetAbsolutePathFromRelative(loc);
3896 delete absoluteFile;