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 isActive { get { return state == running || state == stopped; } }
625 property bool isPrepared { get { return state == loaded || state == running || state == stopped; } }
629 GdbExecContinue(true);
638 ide.DebugUpdateMenus(running, true);
639 GdbDebugBreak(false);
652 GdbDebugBreak(false);
663 property bool isInDebugMode
667 if(state == running || state == stopped)
681 GdbDebugBreak(false);
692 bool GoToCodeLine(char * location)
695 codloc = CodeLocation::ParseCodeLocation(location);
698 CodeEditor editor = (CodeEditor)ide.OpenFile(codloc.absoluteFile, normal, true, null, no, normal);
701 EditBox editBox = editor.editBox;
702 editBox.GoToLineNum(codloc.line - 1);
703 editBox.GoToPosition(editBox.line, codloc.line - 1, 0);
710 bool GoToStackFrameLine(int stackLevel, bool askForLocation)
714 char filePath[MAX_LOCATION];
715 char sourceDir[MAX_LOCATION];
717 CodeEditor editor = null;
718 if(stackLevel == -1) // this (the two lines) is part of that fix that I would not put in for some time
720 for(frame = stackFrames.first; frame; frame = frame.next)
721 if(frame.level == stackLevel)
725 ide.callStackView.Show();
727 if(!frame.absoluteFile && frame.file)
728 frame.absoluteFile = ide.workspace.GetAbsolutePathFromRelative(frame.file);
729 if(!frame.absoluteFile && askForLocation && frame.file)
732 char title[MAX_LOCATION];
734 sprintf(title, "Provide source file location for %s", (s = CopySystemPath(frame.file)));
736 if(SourceDirDialog(title, ide.workspace.projectDir, frame.file, sourceDir))
738 AddSourceDir(sourceDir);
739 frame.absoluteFile = ide.workspace.GetAbsolutePathFromRelative(frame.file);
742 if(frame.absoluteFile)
743 editor = (CodeEditor)ide.OpenFile(frame.absoluteFile, normal, true, null, no, normal);
745 if(editor && frame.line)
747 EditBox editBox = editor.editBox;
748 editBox.GoToLineNum(frame.line - 1);
749 editBox.GoToPosition(editBox.line, frame.line - 1, 0);
757 void SelectThread(int thread)
761 if(thread != activeThread)
763 activeFrameLevel = -1;
764 ide.callStackView.Clear();
765 GdbCommand(false, "-thread-select %d", thread);
767 // Why was SelectFrame missing here?
768 SelectFrame(activeFrameLevel);
769 GoToStackFrameLine(activeFrameLevel, true);
770 WatchesCodeEditorLinkRelease();
771 WatchesCodeEditorLinkInit();
775 ide.callStackView.Show();
779 void SelectFrame(int frame)
783 if(frame != activeFrameLevel || !codeEditor || !codeEditor.visible)
785 activeFrameLevel = frame; // there is no active frame number in the gdb reply
786 GdbCommand(false, "-stack-select-frame %d", activeFrameLevel);
787 for(activeFrame = stackFrames.first; activeFrame; activeFrame = activeFrame.next)
788 if(activeFrame.level == activeFrameLevel)
791 WatchesCodeEditorLinkRelease();
792 WatchesCodeEditorLinkInit();
799 void HandleExit(char * reason, char * code)
801 bool returnedExitCode = false;
802 char verboseExitCode[128];
808 sprintf(verboseExitCode, " with exit code %s", code);
810 verboseExitCode[0] = '\0';
814 // ClearBreakDisplay();
818 for(wh : ide.workspace.watches)
820 if(wh.type) FreeType(wh.type);
823 ide.watchesView.UpdateWatch(wh);
827 ide.DebugUpdateMenus(loaded, false);
829 #if defined(__unix__)
830 progThread.terminate = true;
833 fifoFile.CloseInput();
842 char program[MAX_LOCATION];
843 GetSystemPathBuffer(program, targetFile);
845 ide.outputView.debugBox.Logf("The program %s has exited%s.\n", program, verboseExitCode);
846 else if(!strcmp(reason, "exited-normally"))
847 ide.outputView.debugBox.Logf("The program %s has exited normally%s.\n", program, verboseExitCode);
848 else if(!strcmp(reason, "exited"))
849 ide.outputView.debugBox.Logf("The program %s has exited%s.\n", program, verboseExitCode);
850 else if(!strcmp(reason, "exited-signalled"))
851 ide.outputView.debugBox.Logf("The program %s has exited with a signal%s.\n", program, verboseExitCode);
853 ide.outputView.debugBox.Logf("The program %s has exited (gdb provided an unknown reason)%s.\n", program, verboseExitCode);
860 ide.outputView.debugBox.Clear();
882 ide.outputView.ShowClearSelectTab(debug);
883 ide.outputView.debugBox.Logf("Starting debug mode\n");
884 userBreakOnInternBreak = true;
893 void StepOver(bool ignoreBkpts)
902 ide.outputView.ShowClearSelectTab(debug);
903 ide.outputView.debugBox.Logf("Starting debug mode\n");
904 ignoreBreakpoints = ignoreBkpts;
905 userBreakOnInternBreak = true;
909 ignoreBreakpoints = ignoreBkpts;
910 if(ignoreBreakpoints)
911 GdbBreakpointsDelete(true);
917 void StepOut(bool ignoreBkpts)
921 ignoreBreakpoints = ignoreBkpts;
922 if(ignoreBreakpoints)
923 GdbBreakpointsDelete(true);
928 void RunToCursor(char * absoluteFilePath, int lineNumber, bool ignoreBkpts)
930 char relativeFilePath[MAX_LOCATION];
931 DebuggerState oldState = state;
932 ignoreBreakpoints = ignoreBkpts;
933 if(!ide.projectView.GetRelativePath(absoluteFilePath, relativeFilePath))
934 strcpy(relativeFilePath, absoluteFilePath);
946 ide.outputView.ShowClearSelectTab(debug);
947 ide.outputView.debugBox.Logf("Starting debug mode\n");
949 RunToCursorPrepare(absoluteFilePath, relativeFilePath, lineNumber);
950 sentBreakInsert = true;
951 GdbCommand(false, "-break-insert %s:%d", relativeFilePath, lineNumber);
952 bpRunToCursor.bp = bpItem;
954 bpRunToCursor.inserted = (bpRunToCursor.bp.number != 0);
955 ValidateBreakpoint(bpRunToCursor);
962 if(ignoreBreakpoints)
963 GdbBreakpointsDelete(false);
967 if(ignoreBreakpoints)
968 GdbBreakpointsDelete(false);
969 GdbExecContinue(true);
975 void GetCallStackCursorLine(bool * error, int * lineCursor, int * lineTopFrame)
977 if(activeFrameLevel == -1)
985 *error = signalOn && activeThread == signalThread;
986 *lineCursor = activeFrameLevel + 1;
987 *lineTopFrame = activeFrameLevel ? 1 : 0;
991 int GetMarginIconsLineNumbers(char * fileName, int lines[], bool enabled[], int max, bool * error, int * lineCursor, int * lineTopFrame)
993 char winFilePath[MAX_LOCATION];
994 char * absoluteFilePath = GetSlashPathBuffer(winFilePath, fileName);
996 Iterator<Breakpoint> it { ide.workspace.breakpoints };
997 while(it.Next() && count < max)
999 Breakpoint bp = it.data;
1002 if(bp.absoluteFilePath && bp.absoluteFilePath[0] && !fstrcmp(bp.absoluteFilePath, absoluteFilePath))
1004 lines[count] = bp.line;
1005 enabled[count] = bp.enabled;
1010 if(activeFrameLevel == -1)
1018 *error = signalOn && activeThread == signalThread;
1019 if(activeFrame && activeFrame.absoluteFile && !fstrcmp(absoluteFilePath, activeFrame.absoluteFile))
1020 *lineCursor = activeFrame.line;
1023 if(activeFrame && stopItem && stopItem.frame && activeFrame.level == stopItem.frame.level)
1025 else if(stopItem && stopItem.frame && stopItem.frame.absoluteFile && !fstrcmp(absoluteFilePath, stopItem.frame.absoluteFile))
1026 *lineTopFrame = stopItem.frame.line;
1030 if(*lineTopFrame == *lineCursor && *lineTopFrame)
1036 void ChangeWatch(DataRow row, char * expression)
1038 Watch wh = (Watch)row.tag;
1041 delete wh.expression;
1043 wh.expression = CopyString(expression);
1046 Iterator<Watch> it { ide.workspace.watches };
1048 ide.workspace.watches.Delete(it.pointer);
1055 ide.workspace.watches.Add(wh);
1057 wh.expression = CopyString(expression);
1059 ide.workspace.Save();
1060 //if(expression && state == stopped)
1065 void MoveIcons(char * fileName, int lineNumber, int move, bool start)
1067 char winFilePath[MAX_LOCATION];
1068 char * absoluteFilePath = GetSlashPathBuffer(winFilePath, fileName);
1071 for(bpLink = ide.workspace.breakpoints.first; bpLink; bpLink = next)
1073 Breakpoint bp = (Breakpoint)bpLink.data;
1076 if(bp.type == user && bp.absoluteFilePath && !fstrcmp(bp.absoluteFilePath, absoluteFilePath))
1078 if(bp.line > lineNumber || (bp.line == lineNumber && start))
1080 if(move < 0 && (bp.line < lineNumber - move))
1081 ide.workspace.RemoveBreakpoint(bp);
1085 ide.breakpointsView.UpdateBreakpoint(bp.row);
1086 ide.workspace.Save();
1092 // moving code cursors is futile, on next step, stop, hit, cursors will be offset anyways
1095 bool SourceDirDialog(char * title, char * startDir, char * test, char * sourceDir)
1099 String srcDir = null;
1101 debuggerFileDialog.text = title;
1102 debuggerFileDialog.currentDirectory = startDir;
1103 debuggerFileDialog.master = ide;
1105 while(debuggerFileDialog.Modal())
1107 strcpy(sourceDir, debuggerFileDialog.filePath);
1108 if(!fstrcmp(ide.workspace.projectDir, sourceDir) &&
1109 MessageBox { type = yesNo, master = ide,
1110 contents = "This is the project directory.\nWould you like to try again?",
1111 text = "Invalid Source Directory" }.Modal() == no)
1115 for(dir : ide.workspace.sourceDirs)
1117 if(!fstrcmp(dir, sourceDir))
1125 MessageBox { type = yesNo, master = ide,
1126 contents = "This source directory is already specified.\nWould you like to try again?",
1127 text = "Invalid Source Directory" }.Modal() == no)
1133 char file[MAX_LOCATION];
1134 strcpy(file, sourceDir);
1135 PathCat(file, test);
1136 result = FileExists(file);
1138 MessageBox { type = yesNo, master = ide,
1139 contents = "Unable to locate source file.\nWould you like to try again?",
1140 text = "Invalid Source Directory" }.Modal() == no)
1154 void AddSourceDir(char * sourceDir)
1156 ide.workspace.sourceDirs.Add(CopyString(sourceDir));
1157 ide.workspace.Save();
1161 DebuggerState oldState = state;
1166 GdbDebugBreak(true);
1169 GdbCommand(false, "-environment-directory \"%s\"", sourceDir);
1172 if(oldState == running)
1173 GdbExecContinue(false);
1177 void ToggleBreakpoint(char * fileName, int lineNumber, Project prj)
1179 char winFilePath[MAX_LOCATION];
1180 char * absoluteFilePath = GetSlashPathBuffer(winFilePath, fileName);
1181 char absolutePath[MAX_LOCATION];
1182 char relativePath[MAX_LOCATION];
1183 char sourceDir[MAX_LOCATION];
1184 Breakpoint bp = null;
1186 strcpy(absolutePath, absoluteFilePath);
1187 for(i : ide.workspace.breakpoints; i.type == user && i.absoluteFilePath && !fstrcmp(i.absoluteFilePath, absolutePath) && i.line == lineNumber)
1196 ide.workspace.RemoveBreakpoint(bp);
1204 // FIXED: This is how it should have been... Source locations are only for files not in project
1205 // if(eString_PathInsideOf(absolutePath, ide.workspace.projectDir))
1206 // MakePathRelative(absolutePath, ide.workspace.projectDir, relativePath);
1207 bool result = false;
1209 result = prj.GetRelativePath(absolutePath, relativePath);
1211 ide.projectView.GetRelativePath(absolutePath, relativePath);
1212 //if(ide.projectView.GetRelativePath(absolutePath, relativePath));
1216 char title[MAX_LOCATION];
1217 char directory[MAX_LOCATION];
1218 StripLastDirectory(absolutePath, directory);
1219 sprintf(title, "Provide source files location directory for %s", absolutePath);
1222 String srcDir = null;
1223 for(dir : ide.workspace.sourceDirs)
1225 if(eString_PathInsideOf(absolutePath, dir))
1227 MakePathRelative(absoluteFilePath, dir, relativePath);
1235 if(SourceDirDialog(title, directory, null, sourceDir))
1237 if(eString_PathInsideOf(absolutePath, sourceDir))
1239 AddSourceDir(sourceDir);
1240 MakePathRelative(absoluteFilePath, sourceDir, relativePath);
1243 else if(MessageBox { type = yesNo, master = ide,
1244 contents = "You must provide a valid source directory in order to place a breakpoint in this file.\nWould you like to try again?",
1245 text = "Invalid Source Directory" }.Modal() == no)
1248 else if(MessageBox { type = yesNo, master = ide,
1249 contents = "You must provide a source directory in order to place a breakpoint in this file.\nWould you like to try again?",
1250 text = "No Source Directory Provided" }.Modal() == no)
1254 ide.workspace.bpCount++;
1255 bp = { line = lineNumber, type = user, enabled = true, level = -1 };
1256 ide.workspace.breakpoints.Add(bp);
1257 bp.absoluteFilePath = CopyString(absolutePath);
1258 bp.relativeFilePath = CopyString(relativePath);
1259 ide.breakpointsView.AddBreakpoint(bp);
1264 DebuggerState oldState = state;
1269 GdbDebugBreak(true);
1274 sentBreakInsert = true;
1275 GdbCommand(false, "-break-insert %s:%d", bp.relativeFilePath, bp.line);
1278 bp.inserted = (bp.bp && bp.bp.number != 0);
1279 ValidateBreakpoint(bp);
1283 if(oldState == running)
1284 GdbExecContinue(false);
1287 ide.workspace.Save();
1290 void UpdateRemovedBreakpoint(Breakpoint bp)
1292 if(targeted && bp.inserted)
1294 DebuggerState oldState = state;
1299 GdbDebugBreak(true);
1303 GdbCommand(false, "-break-delete %d", bp.bp.number);
1306 if(oldState == running)
1307 GdbExecContinue(false);
1313 void ParseFrame(Frame frame, char * string)
1316 Array<char *> frameTokens { minAllocSize = 50 };
1317 Array<char *> argsTokens { minAllocSize = 50 };
1318 Array<char *> argumentTokens { minAllocSize = 50 };
1319 DebugListItem item { };
1322 TokenizeList(string, ',', frameTokens);
1323 for(i = 0; i < frameTokens.count; i++)
1325 if(TokenizeListItem(frameTokens[i], item))
1327 StripQuotes(item.value, item.value);
1328 if(!strcmp(item.name, "level"))
1329 frame.level = atoi(item.value);
1330 else if(!strcmp(item.name, "addr"))
1331 frame.addr = CopyString(item.value);
1332 else if(!strcmp(item.name, "func"))
1333 frame.func = CopyString(item.value);
1334 else if(!strcmp(item.name, "args"))
1336 if(!strcmp(item.value, "[]"))
1337 frame.argsCount = 0;
1340 item.value = StripBrackets(item.value);
1341 TokenizeList(item.value, ',', argsTokens);
1342 for(j = 0; j < argsTokens.count; j++)
1344 argsTokens[j] = StripCurlies(argsTokens[j]);
1345 TokenizeList(argsTokens[j], ',', argumentTokens);
1346 for(k = 0; k < argumentTokens.count; k++)
1349 frame.args.Add(arg);
1350 if(TokenizeListItem(argumentTokens[k], item))
1352 if(!strcmp(item.name, "name"))
1354 StripQuotes(item.value, item.value);
1355 arg.name = CopyString(item.value);
1357 else if(!strcmp(item.name, "value"))
1359 StripQuotes(item.value, item.value);
1360 arg.value = CopyString(item.value);
1363 DebuggerProtocolUnknown("Unknown frame args item name", item.name);
1366 DebuggerProtocolUnknown("Bad frame args item", "");
1368 argumentTokens.RemoveAll();
1370 frame.argsCount = argsTokens.count;
1371 argsTokens.RemoveAll();
1374 else if(!strcmp(item.name, "from"))
1375 frame.from = item.value;
1376 else if(!strcmp(item.name, "file"))
1378 frame.file = item.value;
1379 frame.absoluteFile = ide.workspace.GetAbsolutePathFromRelative(frame.file);
1381 else if(!strcmp(item.name, "line"))
1382 frame.line = atoi(item.value);
1383 else if(!strcmp(item.name, "fullname"))
1385 // New GDB is giving us a full name... Any reason why we coudln't figure it out ourselves?
1388 DebuggerProtocolUnknown("Unknown frame member name", item.name);
1391 DebuggerProtocolUnknown("Bad frame", "");
1396 delete argumentTokens;
1400 void ShowDebuggerViews()
1402 ide.outputView.Show();
1403 ide.outputView.SelectTab(debug);
1404 ide.threadsView.Show();
1405 ide.callStackView.Show();
1406 ide.watchesView.Show();
1410 void HideDebuggerViews()
1412 ide.RepositionWindows(true);
1415 void ::GdbCommand(bool focus, char * format, ...)
1419 char string[MAX_F_STRING];
1422 va_start(args, format);
1423 vsprintf(string, format, args);
1427 ide.debugger.serialSemaphore.TryWait();
1430 #ifdef GDB_DEBUG_CONSOLE
1431 Log(string); Log("\n");
1433 #ifdef GDB_DEBUG_OUTPUT
1434 ide.outputView.gdbBox.Logf("cmd: %s\n", string);
1436 #ifdef GDB_DEBUG_GUI
1438 ide.gdbDialog.AddCommand(string);
1440 gdbHandle.Printf("%s\n", string);
1443 Process_ShowWindows(targetProcessId);
1446 ide.debugger.serialSemaphore.Wait();
1451 bool ValidateBreakpoint(Breakpoint bp)
1455 if(bp.bp.line != bp.line)
1460 ide.outputView.debugBox.Logf("WOULD HAVE -- Invalid breakpoint disabled: %s:%d\n", bp.relativeFilePath, bp.line);
1464 //GdbCommand(false, "-break-delete %d", bp.bp.number);
1465 //bp.inserted = false;
1467 //bp.enabled = false;
1472 ide.outputView.debugBox.Logf("Debugger Error: ValidateBreakpoint error\n");
1473 bp.line = bp.bp.line;
1480 static void GdbInsertInternalBreakpoint()
1484 //if(!breakpointsInserted)
1486 DirExpression objDir = ide.project.objDir;
1491 if(bp.type == internalMain)
1493 sentBreakInsert = true;
1494 GdbCommand(false, "-break-insert main");
1497 bp.inserted = (bp.bp && bp.bp.number != 0);
1499 #if defined(__WIN32__)
1500 else if(bp.type == internalWinMain)
1502 sentBreakInsert = true;
1503 GdbCommand(false, "-break-insert WinMain");
1506 bp.inserted = (bp.bp && bp.bp.number != 0);
1509 else if(bp.type == internalModulesLoaded)
1511 char path[MAX_LOCATION];
1512 char name[MAX_LOCATION];
1513 char fixedModuleName[MAX_FILENAME];
1516 bool moduleLoadBlock = false;
1518 ReplaceSpaces(fixedModuleName, ide.project.moduleName);
1519 sprintf(name, "%s.main.ec", fixedModuleName);
1520 strcpy(path, ide.workspace.projectDir);
1521 PathCatSlash(path, objDir.dir);
1522 PathCatSlash(path, name);
1523 f = FileOpen(path, read);
1526 for(lineNumber = 1; !f.Eof(); lineNumber++)
1528 if(f.GetLine(line, sizeof(line) - 1))
1530 bool moduleLoadLine;
1531 TrimLSpaces(line, line);
1532 moduleLoadLine = !strncmp(line, "eModule_Load", strlen("eModule_Load"));
1533 if(!moduleLoadBlock && moduleLoadLine)
1534 moduleLoadBlock = true;
1535 else if(moduleLoadBlock && !moduleLoadLine && strlen(line) > 0)
1541 char relative[MAX_LOCATION];
1542 bp.absoluteFilePath = CopyString(path);
1543 MakePathRelative(path, ide.workspace.projectDir, relative);
1544 delete bp.relativeFilePath;
1545 bp.relativeFilePath = CopyString(relative);
1546 bp.line = lineNumber;
1547 sentBreakInsert = true;
1548 GdbCommand(false, "-break-insert %s:%d", bp.relativeFilePath, lineNumber);
1551 bp.inserted = (bp.bp && bp.bp.number != 0);
1552 ValidateBreakpoint(bp);
1565 void GdbBreakpointsInsert()
1569 //if(!breakpointsInserted)
1571 //if(!ignoreBreakpoints)
1572 //breakpointsInserted = true;
1573 for(bp : ide.workspace.breakpoints)
1575 if(!bp.inserted && bp.type == user)
1577 if(!ignoreBreakpoints && bp.enabled)
1579 sentBreakInsert = true;
1580 GdbCommand(false, "-break-insert %s:%d", bp.relativeFilePath, bp.line);
1583 bp.inserted = (bp.bp && bp.bp.number != 0);
1585 ValidateBreakpoint(bp);
1591 printf("problem\n");
1593 bp.bp = GdbDataBreakpoint { };
1597 if(bpRunToCursor && !bpRunToCursor.inserted)
1599 sentBreakInsert = true;
1600 GdbCommand(false, "-break-insert %s:%d", bpRunToCursor.relativeFilePath, bpRunToCursor.line);
1601 bpRunToCursor.bp = bpItem;
1603 bpRunToCursor.inserted = (bpRunToCursor.bp && bpRunToCursor.bp.number != 0);
1604 ValidateBreakpoint(bpRunToCursor);
1610 void GdbBreakpointsDelete(bool deleteRunToCursor)
1612 //breakpointsInserted = false;
1615 for(bp : ide.workspace.breakpoints)
1618 GdbCommand(false, "-break-delete %d", bp.bp.number);
1619 bp.inserted = false;
1621 //check here (reply form -break-delete, returns bpitem?)
1624 if(deleteRunToCursor && bpRunToCursor)
1626 GdbCommand(false, "-break-delete %d", bpRunToCursor.bp.number);
1627 bpRunToCursor.inserted = false;
1628 bpRunToCursor.bp = bpItem;
1629 //check here (reply form -break-delete, returns bpitem?)
1638 stackFrames.Free(Frame::Free);
1639 GdbCommand(false, "-stack-info-depth");
1641 GdbCommand(false, "-stack-info-depth 192");
1642 if(frameCount && frameCount <= 192)
1643 GdbCommand(false, "-stack-list-frames 0 191");
1646 GdbCommand(false, "-stack-list-frames 0 95");
1647 GdbCommand(false, "-stack-list-frames %d %d", Max(frameCount - 96, 96), frameCount - 1);
1649 GdbCommand(false, "");
1656 char escaped[MAX_LOCATION];
1657 strescpy(escaped, targetFile);
1658 GdbCommand(false, "file \"%s\"", escaped); //GDB/MI Missing Implementation -symbol-file, -target-attach
1663 for(prj : ide.workspace.projects)
1665 if(prj == ide.workspace.projects.firstIterator.data)
1668 //PrintLn("THIS: ", (String)prj.topNode.path);
1669 GdbCommand(false, "-environment-directory \"%s\"", prj.topNode.path);
1670 //GdbCommand(false, ""); // why this empty GDB command
1673 for(dir : ide.workspace.sourceDirs)
1675 GdbCommand(false, "-environment-directory \"%s\"", dir);
1676 //GdbCommand(false, ""); // why this empty GDB command
1678 GdbInsertInternalBreakpoint();
1684 void GdbTargetRelease()
1688 GdbBreakpointsDelete(true);
1689 GdbCommand(false, "file"); //GDB/MI Missing Implementation -target-detach
1695 void GdbDebugBreak(bool internal)
1700 breakType = DebuggerAction::internal;
1704 ide.DebugUpdateMenus(running, true);
1708 if(Process_Break(targetProcessId)) //GdbCommand(false, "-exec-interrupt");
1709 serialSemaphore.Wait();
1713 targetProcessId = 0;
1714 ide.DebugUpdateMenus(loaded, false);
1719 ide.outputView.debugBox.Logf("Debugger Error: GdbDebugBreak with not target id should never happen\n");
1726 ShowDebuggerViews();
1727 GdbCommand(true, "-exec-run");
1730 void GdbExecContinue(bool focus)
1733 GdbCommand(focus, "-exec-continue");
1739 GdbCommand(true, "-exec-next");
1745 GdbCommand(true, "-exec-step");
1748 void GdbExecFinish()
1751 GdbCommand(true, "-exec-finish");
1754 void GdbExecCommon()
1756 ClearBreakDisplay();
1757 GdbBreakpointsInsert();
1760 #ifdef GDB_DEBUG_GUI
1761 void SendGDBCommand(char * command)
1763 DebuggerState oldState = state;
1768 GdbDebugBreak(true);
1771 GdbCommand(false, command);
1774 if(oldState == running)
1775 GdbExecContinue(false);
1779 void ClearBreakDisplay()
1782 activeFrameLevel = -1;
1793 stackFrames.Free(Frame::Free);
1794 WatchesCodeEditorLinkRelease();
1795 ide.callStackView.Clear();
1796 ide.threadsView.Clear();
1803 GdbCommand(false, "-interpreter-exec console \"kill\""); // should use -exec-abort -- GDB/MI implementation incomplete
1810 char oldDirectory[MAX_LOCATION];
1811 char tempPath[MAX_LOCATION];
1812 char command[MAX_LOCATION];
1813 char oldPath[MAX_LOCATION * 65];
1814 Project project = ide.project;
1815 DirExpression targetDirExp = project.targetDir;
1817 GetEnvironment("PATH", oldPath, sizeof(oldPath));
1819 prjConfig = project.config;
1823 sentBreakInsert = false;
1827 //breakpointsInserted = false;
1829 ide.outputView.ShowClearSelectTab(debug);
1830 ide.outputView.debugBox.Logf("Starting debug mode\n");
1832 #ifdef GDB_DEBUG_CONSOLE
1833 Log("Starting GDB"); Log("\n");
1835 #ifdef GDB_DEBUG_OUTPUT
1836 ide.outputView.gdbBox.Logf("run: Starting GDB\n");
1839 strcpy(tempPath, ide.workspace.projectDir);
1840 PathCatSlash(tempPath, targetDirExp.dir);
1842 targetDir = CopyString(tempPath);
1843 project.CatTargetFileName(tempPath);
1845 targetFile = CopyString(tempPath);
1847 GetWorkingDir(oldDirectory, MAX_LOCATION);
1848 if(ide.workspace.debugDir && ide.workspace.debugDir[0])
1850 char temp[MAX_LOCATION];
1851 strcpy(temp, ide.workspace.projectDir);
1852 PathCatSlash(temp, ide.workspace.debugDir);
1853 ChangeWorkingDir(temp);
1856 ChangeWorkingDir(ide.workspace.projectDir);
1860 sprintf(command, "gdb -n -silent --interpreter=mi2"); //-async //\"%s\"
1862 gdbHandle = DualPipeOpen(PipeOpenMode { output = 1, error = 2, input = 1 }, command);
1865 ide.outputView.debugBox.Logf("Debugger Fatal Error: Couldn't start GDB\n");
1873 gdbProcessId = gdbHandle.GetProcessID();
1876 ide.outputView.debugBox.Logf("Debugger Fatal Error: Couldn't get GDB process ID\n");
1882 serialSemaphore.Wait();
1887 //state = terminated;
1888 //ide.DebugUpdateMenus(loaded, false);
1894 #if defined(__unix__)
1896 CreateTemporaryDir(progFifoDir, "ecereide");
1897 strcpy(progFifoPath, progFifoDir);
1898 PathCat(progFifoPath, "ideprogfifo");
1899 if(!mkfifo(progFifoPath, 0600))
1901 //fileCreated = true;
1906 ide.outputView.debugBox.Logf("err: Unable to create FIFO %s\n", progFifoPath);
1911 progThread.terminate = false;
1912 progThread.Create();
1915 #if defined(__WIN32__)
1916 GdbCommand(false, "-gdb-set new-console on");
1919 GdbCommand(false, "-gdb-set verbose off");
1920 //GdbCommand(false, "-gdb-set exec-done-display on");
1921 GdbCommand(false, "-gdb-set step-mode off");
1922 GdbCommand(false, "-gdb-set unwindonsignal on");
1923 //GdbCommand(false, "-gdb-set shell on");
1924 GdbCommand(false, "set print elements 992");
1925 GdbCommand(false, "-gdb-set backtrace limit 100000");
1927 #if defined(__unix__)
1928 GdbCommand(false, "-inferior-tty-set %s", progFifoPath);
1931 GdbCommand(false, "-gdb-set args %s", ide.workspace.commandLineArgs ? ide.workspace.commandLineArgs : "");
1936 ChangeWorkingDir(oldDirectory);
1937 SetEnvironment("PATH", oldPath);
1941 delete targetDirExp;
1947 if(gdbHandle && gdbProcessId)
1949 GdbCommand(false, "-gdb-exit");
1968 for(bp : ide.workspace.breakpoints)
1969 bp.inserted = false;
1971 bp.inserted = false;
1973 bpRunToCursor.inserted = false;
1975 ide.outputView.debugBox.Logf("Debugging stopped\n");
1976 ClearBreakDisplay();
1977 ide.DebugUpdateMenus(loaded, false);
1980 #if defined(__unix__)
1981 if(FileExists(progFifoPath)) //fileCreated)
1983 progThread.terminate = true;
1986 fifoFile.CloseInput();
1992 DeleteFile(progFifoPath);
1993 progFifoPath[0] = '\0';
1999 void WatchesCodeEditorLinkInit()
2002 char tempPath[MAX_LOCATION];
2003 char path[MAX_LOCATION];
2005 //void MakeFilePathProjectRelative(char * path, char * relativePath)
2006 if(!ide.projectView.GetRelativePath(activeFrame.file, tempPath))
2007 strcpy(tempPath, activeFrame.file);
2009 strcpy(path, ide.workspace.projectDir);
2010 PathCat(path, tempPath);
2011 codeEditor = (CodeEditor)ide.OpenFile(path, Normal, false, null, no);
2014 for(srcDir : ide.workspace.sourceDirs)
2016 strcpy(path, srcDir);
2017 PathCat(path, tempPath);
2018 codeEditor = (CodeEditor)ide.OpenFile(path, Normal, false, null, no);
2019 if(codeEditor) break;
2024 if(activeFrame && !activeFrame.absoluteFile && activeFrame.file)
2025 activeFrame.absoluteFile = ide.workspace.GetAbsolutePathFromRelative(activeFrame.file);
2026 if(!activeFrame || !activeFrame.absoluteFile)
2029 codeEditor = (CodeEditor)ide.OpenFile(activeFrame.absoluteFile, normal, false, null, no, normal);
2032 codeEditor.inUseDebug = true;
2035 //watchesInit = true;
2038 void WatchesCodeEditorLinkRelease()
2044 codeEditor.inUseDebug = false;
2045 if(!codeEditor.visible)
2046 codeEditor.Destroy(0);
2052 bool ResolveWatch(Watch wh)
2054 bool result = false;
2067 char watchmsg[MAX_F_STRING];
2068 if(state == stopped && !codeEditor)
2069 wh.value = CopyString("No source file found for selected frame");
2070 //if(codeEditor && state == stopped || state != stopped)
2073 Module backupPrivateModule;
2074 Context backupContext;
2075 Class backupThisClass;
2079 backupPrivateModule = GetPrivateModule();
2080 backupContext = GetCurrentContext();
2081 backupThisClass = GetThisClass();
2084 SetPrivateModule(codeEditor.privateModule);
2085 SetCurrentContext(codeEditor.globalContext);
2086 SetTopContext(codeEditor.globalContext);
2087 SetGlobalContext(codeEditor.globalContext);
2088 SetGlobalData(&codeEditor.globalData);
2091 exp = ParseExpressionString(wh.expression);
2093 if(exp && !parseError)
2095 if(GetPrivateModule())
2098 DebugFindCtxTree(codeEditor.ast, activeFrame.line, 0);
2099 ProcessExpressionType(exp);
2101 wh.type = exp.expType;
2104 DebugComputeExpression(exp);
2106 /*if(exp.hasAddress)
2108 char temp[MAX_F_STRING];
2109 sprintf(temp, "0x%x", exp.address);
2110 wh.address = CopyString(temp);
2111 // wh.address = CopyStringf("0x%x", exp.address);
2116 Type dataType = exp.expType;
2119 char temp[MAX_F_STRING];
2120 switch(dataType.kind)
2123 sprintf(temp, "%i", exp.val.c);
2126 sprintf(temp, "%i", exp.val.s);
2131 sprintf(temp, "%i", exp.val.i);
2134 sprintf(temp, "%i", exp.val.i64);
2137 sprintf(temp, "%i", exp.val.p);
2142 long v = (long)exp.val.f;
2143 sprintf(temp, "%i", v);
2148 long v = (long)exp.val.d;
2149 sprintf(temp, "%i", v);
2154 wh.intVal = CopyString(temp);
2155 switch(dataType.kind)
2158 sprintf(temp, "0x%x", exp.val.c);
2161 sprintf(temp, "0x%x", exp.val.s);
2165 sprintf(temp, "0x%x", exp.val.i);
2168 sprintf(temp, "0x%x", exp.val.i64);
2171 sprintf(temp, "0x%x", exp.val.i64);
2174 sprintf(temp, "0x%x", exp.val.p);
2179 long v = (long)exp.val.f;
2180 sprintf(temp, "0x%x", v);
2185 long v = (long)exp.val.d;
2186 sprintf(temp, "0x%x", v);
2191 wh.hexVal = CopyString(temp);
2192 switch(dataType.kind)
2195 sprintf(temp, "0o%o", exp.val.c);
2198 sprintf(temp, "0o%o", exp.val.s);
2202 sprintf(temp, "0o%o", exp.val.i);
2205 sprintf(temp, "0o%o", exp.val.i64);
2208 sprintf(temp, "0o%o", exp.val.i64);
2211 sprintf(temp, "0o%o", exp.val.p);
2216 long v = (long)exp.val.f;
2217 sprintf(temp, "0o%o", v);
2222 long v = (long)exp.val.d;
2223 sprintf(temp, "0o%o", v);
2228 wh.octVal = CopyString(temp);
2231 // WHATS THIS HERE ?
2232 if(exp.type == constantExp && exp.constant)
2233 wh.constant = CopyString(exp.constant);
2239 case symbolErrorExp:
2240 sprintf(watchmsg, "Symbol \"%s\" not found", exp.identifier.string);
2242 case structMemberSymbolErrorExp:
2243 // todo get info as in next case (ExpClassMemberSymbolError)
2244 sprintf(watchmsg, "Error: Struct member not found for \"%s\"", wh.expression);
2246 case classMemberSymbolErrorExp:
2249 Expression memberExp = exp.member.exp;
2250 Identifier memberID = exp.member.member;
2251 Type type = memberExp.expType;
2254 _class = (memberID && memberID.classSym) ? memberID.classSym.registered : ((type.kind == classType && type._class) ? type._class.registered : null);
2257 char string[256] = "";
2259 PrintType(type, string, false, true);
2260 classSym = FindClass(string);
2261 _class = classSym ? classSym.registered : null;
2264 sprintf(watchmsg, "Member \"%s\" not found in class \"%s\"", memberID ? memberID.string : "", _class.name);
2266 sprintf(watchmsg, "Member \"%s\" not found in unregistered class? (Should never get this message)", memberID ? memberID.string : "");
2269 sprintf(watchmsg, "Member \"%s\" not found in no type? (Should never get this message)", memberID ? memberID.string : "");
2272 case memoryErrorExp:
2273 sprintf(watchmsg, "Memory can't be read at %s", (exp.type == constantExp) ? exp.constant : null);
2275 case dereferenceErrorExp:
2276 sprintf(watchmsg, "Dereference failure for \"%s\"", wh.expression);
2278 case unknownErrorExp:
2279 sprintf(watchmsg, "Unknown error for \"%s\"", wh.expression);
2281 case noDebuggerErrorExp:
2282 sprintf(watchmsg, "Debugger required for symbol evaluation in \"%s\"", wh.expression);
2284 case debugStateErrorExp:
2285 sprintf(watchmsg, "Incorrect debugger state for symbol evaluation in \"%s\"", wh.expression);
2288 sprintf(watchmsg, "Null type for \"%s\"", wh.expression);
2292 // Temporary Code for displaying Strings
2293 if((exp.expType && ((exp.expType.kind == pointerType ||
2294 exp.expType.kind == arrayType) && exp.expType.type.kind == charType)) ||
2295 (wh.type && wh.type.kind == classType && wh.type._class &&
2296 wh.type._class.registered && wh.type._class.registered.type == normalClass &&
2297 !strcmp(wh.type._class.registered.name, "String")))
2300 if(exp.expType.kind != arrayType || exp.hasAddress)
2306 //char temp[MAX_F_STRING * 32];
2308 ExpressionType evalError = dummyExp;
2309 /*if(exp.expType.kind == arrayType)
2310 sprintf(temp, "(char*)0x%x", exp.address);
2312 sprintf(temp, "(char*)%s", exp.constant);*/
2314 //evaluation = Debugger::EvaluateExpression(temp, &evalError);
2315 address = strtoul(exp.constant, null, 0);
2316 //printf("%x\n", address);
2317 sprintf(value, "0x%08x ", address);
2320 strcat(value, "Null string");
2324 len = strlen(value);
2326 while(!string && size > 2)
2328 string = GdbReadMemory(address, size);
2331 if(string && string[0])
2334 if(UTF8Validate(string))
2339 for(c = 0; (ch = string[c]) && c<4096; c++)
2342 value[len++] = '\0';
2347 ISO8859_1toUTF8(string, value + len, 4096 - len - 30);
2348 strcat(value, ") (ISO8859-1)");
2355 strcat(value, "Empty string");
2359 strcat(value, "Couldn't read memory");
2361 wh.value = CopyString(value);
2364 else if(wh.type && wh.type.kind == classType && wh.type._class &&
2365 wh.type._class.registered && wh.type._class.registered.type == enumClass)
2367 uint64 value = strtoul(exp.constant, null, 0);
2368 Class enumClass = eSystem_FindClass(GetPrivateModule(), wh.type._class.registered.name);
2369 EnumClassData enumeration = (EnumClassData)enumClass.data;
2371 for(item = enumeration.values.first; item; item = item.next)
2372 if((int)item.data == value)
2375 wh.value = CopyString(item.name);
2377 wh.value = CopyString("Invalid Enum Value");
2378 result = (bool)atoi(exp.constant);
2380 else if(wh.type && (wh.type.kind == charType || (wh.type.kind == classType && wh.type._class &&
2381 wh.type._class.registered && !strcmp(wh.type._class.registered.fullName, "ecere::com::unichar"))) )
2388 if(exp.constant[0] == '\'')
2390 if((int)((byte *)exp.constant)[1] > 127)
2393 value = UTF8GetChar(exp.constant + 1, &nb);
2394 if(nb < 2) value = exp.constant[1];
2395 signedValue = value;
2399 signedValue = exp.constant[1];
2401 // Precomp Syntax error with boot strap here:
2402 byte b = (byte)(char)signedValue;
2403 value = (unichar) b;
2409 if(wh.type.kind == charType && wh.type.isSigned)
2411 signedValue = (int)(char)strtol(exp.constant, null, 0);
2413 // Precomp Syntax error with boot strap here:
2414 byte b = (byte)(char)signedValue;
2415 value = (unichar) b;
2420 value = strtoul(exp.constant, null, 0);
2421 signedValue = (int)value;
2425 UTF32toUTF8Len(&value, 1, charString, 5);
2427 sprintf(string, "\'\\0' (0)");
2428 else if(value == '\t')
2429 sprintf(string, "\'\\t' (%d)", value);
2430 else if(value == '\n')
2431 sprintf(string, "\'\\n' (%d)", value);
2432 else if(value == '\r')
2433 sprintf(string, "\'\\r' (%d)", value);
2434 else if(wh.type.kind == charType && wh.type.isSigned)
2435 sprintf(string, "\'%s\' (%d)", charString, signedValue);
2436 else if(value > 256 || wh.type.kind != charType)
2438 if(value > 0x10FFFF || !GetCharCategory(value))
2439 sprintf(string, "Invalid Unicode Keypoint (0x%08X)", value);
2441 sprintf(string, "\'%s\' (U+%04X)", charString, value);
2444 sprintf(string, "\'%s\' (%d)", charString, value);
2446 wh.value = CopyString(string);
2451 wh.value = CopyString(exp.constant);
2452 result = (bool)atoi(exp.constant);
2458 wh.value = PrintHexUInt(exp.address);
2459 result = (bool)exp.address;
2463 char tempString[256];
2464 sprintf(watchmsg, "Evaluation failed for \"%s\" of type \"%s\"", wh.expression,
2465 exp.type.OnGetString(tempString, null, null));
2471 sprintf(watchmsg, "Invalid expression: \"%s\"", wh.expression);
2472 if(exp) FreeExpression(exp);
2475 SetPrivateModule(backupPrivateModule);
2476 SetCurrentContext(backupContext);
2477 SetTopContext(backupContext);
2478 SetGlobalContext(backupContext);
2479 SetThisClass(backupThisClass);
2482 // wh.value = CopyString("No source file found for selected frame");
2485 wh.value = CopyString(watchmsg);
2487 ide.watchesView.UpdateWatch(wh);
2491 void EvaluateWatches()
2493 for(wh : ide.workspace.watches)
2497 char * ::GdbEvaluateExpression(char * expression)
2501 GdbCommand(false, "-data-evaluate-expression \"%s\"", expression);
2503 ide.outputView.debugBox.Logf("Debugger Error: GdbEvaluateExpression\n");
2507 // to be removed... use GdbReadMemory that returns a byte array instead
2508 char * ::GdbReadMemoryString(uint address, int size, char format, int rows, int cols)
2512 GdbCommand(false, "-data-read-memory 0x%08x %c, %d, %d, %d", address, format, size, rows, cols);
2514 ide.outputView.debugBox.Logf("Debugger Error: GdbReadMemoryString\n");
2518 byte * ::GdbReadMemory(uint address, int bytes)
2522 GdbCommand(false, "-data-read-memory 0x%08x %c, 1, 1, %d", address, 'u', bytes);
2524 ide.outputView.debugBox.Logf("Debugger Error: GdbReadMemory\n");
2525 else if(eval.result && strcmp(eval.result, "N/A"))
2527 byte * result = new byte[bytes];
2528 byte * string = eval.result;
2532 result[c++] = (byte)strtol(string, &string, 10);
2548 void EventHit(GdbDataStop stopItem)
2550 bool conditionMet = true;
2551 Breakpoint bp = bpHit;
2553 if(!bp && bpRunToCursor)
2557 GdbCommand(false, "-break-delete %d", bp.bp.number);
2562 if(bp.type == user && bp.line != stopItem.frame.line)
2564 bp.line = stopItem.frame.line;
2565 ide.breakpointsView.UpdateBreakpoint(bp.row);
2566 ide.workspace.Save();
2572 case internalWinMain:
2573 GdbBreakpointsInsert();
2574 if(userBreakOnInternBreak)
2576 userBreakOnInternBreak = false;
2577 // Why was SelectFrame missing here?
2578 SelectFrame(activeFrameLevel);
2579 GoToStackFrameLine(activeFrameLevel, true);
2580 ide.DebugUpdateMenus(stopped, false);
2585 GdbExecContinue(false);
2587 case internalModulesLoaded:
2589 GdbBreakpointsInsert();
2590 GdbExecContinue(false);
2595 conditionMet = ResolveWatch(bp.condition);
2596 if(conditionMet && (bp.level == -1 || bp.level == frameCount))
2599 if(bp.hits > bp.ignore)
2601 ignoreBreakpoints = false;
2602 // Why was SelectFrame missing here?
2603 SelectFrame(activeFrameLevel);
2604 GoToStackFrameLine(activeFrameLevel, true);
2605 ide.DebugUpdateMenus(stopped, false);
2608 if(bp.type == BreakpointType::runToCursor)
2610 delete bpRunToCursor;
2611 bpRunToCursor = null;
2617 ide.breakpointsView.UpdateBreakpoint(bp.row);*/
2618 GdbExecContinue(false);
2622 GdbExecContinue(false);
2627 ide.outputView.debugBox.Logf("Debugger Error: Breakpoint hit could not match breakpoint instance\n");
2630 void GdbThreadExit()
2632 if(state != terminated)
2635 targetProcessId = 0;
2636 ClearBreakDisplay();
2637 ide.DebugUpdateMenus(loaded, false);
2641 serialSemaphore.Release();
2646 ide.outputView.debugBox.Logf("Debugger Fatal Error: GDB lost\n");
2647 ide.outputView.debugBox.Logf("Debugging stopped\n");
2650 //state = terminated;
2654 void GdbThreadMain(char * output)
2657 Array<char *> outTokens { minAllocSize = 50 };
2658 Array<char *> subTokens { minAllocSize = 50 };
2659 DebugListItem item { };
2660 DebugListItem item2 { };
2661 bool setWaitingForPID = false;
2663 #if defined(GDB_DEBUG_CONSOLE) || defined(GDB_DEBUG_GUI)
2664 #ifdef GDB_DEBUG_CONSOLE
2665 Log(output); Log("\n");
2667 #ifdef GDB_DEBUG_OUTPUT
2669 int len = strlen(output);
2677 for(c = 0; c < len / 1024; c++)
2679 strncpy(tmp, start, 1024);
2680 ide.outputView.gdbBox.Logf("out: %s\n", tmp);
2683 ide.outputView.gdbBox.Logf("out: %s\n", start);
2687 ide.outputView.gdbBox.Logf("out: %s\n", output);
2691 #ifdef GDB_DEBUG_CONSOLE
2692 strcpy(lastGdbOutput, output);
2694 #ifdef GDB_DEBUG_GUI
2695 if(ide.gdbDialog) ide.gdbDialog.AddOutput(output);
2702 if(strstr(output, "No debugging symbols found") || strstr(output, "(no debugging symbols found)"))
2705 ide.outputView.debugBox.Logf("Target doesn't contain debug information!\n");
2711 if(TokenizeList(output, ',', outTokens) && !strcmp(outTokens[0], "^done"))
2713 //if(outTokens.count == 1)
2719 targetProcessId = 0;
2720 if(outTokens.count > 1 && TokenizeListItem(outTokens[1], item))
2722 if(!strcmp(item.name, "reason"))
2724 char * reason = item.value;
2725 StripQuotes(reason, reason);
2726 if(!strcmp(reason, "exited-normally") || !strcmp(reason, "exited") || !strcmp(reason, "exited-signalled"))
2729 if(outTokens.count > 2 && TokenizeListItem(outTokens[2], item2))
2731 StripQuotes(item2.value, item2.value);
2732 if(!strcmp(item2.name, "exit-code"))
2733 exitCode = item2.value;
2739 HandleExit(reason, exitCode);
2743 DebuggerProtocolUnknown("Unknown kill reply", item.name);
2746 HandleExit(null, null);
2749 if(outTokens.count > 1 && TokenizeListItem(outTokens[1], item))
2751 if(!strcmp(item.name, "bkpt"))
2753 sentBreakInsert = false;
2756 printf("problem\n");
2758 bpItem = GdbDataBreakpoint { };
2759 item.value = StripCurlies(item.value);
2760 TokenizeList(item.value, ',', subTokens);
2761 for(i = 0; i < subTokens.count; i++)
2763 if(TokenizeListItem(subTokens[i], item))
2765 StripQuotes(item.value, item.value);
2766 if(!strcmp(item.name, "number"))
2767 bpItem.number = atoi(item.value);
2768 else if(!strcmp(item.name, "type"))
2769 bpItem.type = CopyString(item.value);
2770 else if(!strcmp(item.name, "disp"))
2771 bpItem.disp = CopyString(item.value);
2772 else if(!strcmp(item.name, "enabled"))
2773 bpItem.enabled = (!strcmpi(item.value, "y"));
2774 else if(!strcmp(item.name, "addr"))
2775 bpItem.addr = CopyString(item.value);
2776 else if(!strcmp(item.name, "func"))
2777 bpItem.func = CopyString(item.value);
2778 else if(!strcmp(item.name, "file"))
2779 bpItem.file = item.value;
2780 else if(!strcmp(item.name, "line"))
2781 bpItem.line = atoi(item.value);
2782 else if(!strcmp(item.name, "at"))
2783 bpItem.at = CopyString(item.value);
2784 else if(!strcmp(item.name, "times"))
2785 bpItem.times = atoi(item.value);
2788 //breakType = bpValidation;
2789 //app.SignalEvent();
2790 subTokens.RemoveAll();
2792 else if(!strcmp(item.name, "BreakpointTable"))
2793 ide.outputView.debugBox.Logf("Debugger Error: Command reply BreakpointTable not handled\n");
2794 else if(!strcmp(item.name, "depth"))
2796 StripQuotes(item.value, item.value);
2797 frameCount = atoi(item.value);
2799 stackFrames.Free(Frame::Free);
2801 else if(!strcmp(item.name, "stack"))
2804 if(stackFrames.count)
2805 ide.callStackView.Logf("...\n");
2808 item.value = StripBrackets(item.value);
2809 TokenizeList(item.value, ',', subTokens);
2810 for(i = 0; i < subTokens.count; i++)
2812 if(TokenizeListItem(subTokens[i], item))
2814 if(!strcmp(item.name, "frame"))
2817 stackFrames.Add(frame);
2818 item.value = StripCurlies(item.value);
2819 ParseFrame(frame, item.value);
2820 if(frame.file && frame.from)
2821 DebuggerProtocolUnknown("Unexpected frame file and from members present", "");
2825 if(activeFrameLevel == -1)
2827 if(ide.projectView.IsModuleInProject(frame.file));
2829 if(frame.level != 0)
2831 //stopItem.frame = frame;
2832 breakType = selectFrame;
2835 activeFrame = frame;
2836 activeFrameLevel = frame.level;
2839 ide.callStackView.Logf("%3d ", frame.level);
2840 if(!strncmp(frame.func, "__ecereMethod_", strlen("__ecereMethod_")))
2841 ide.callStackView.Logf("%s Method, %s:%d\n", &frame.func[strlen("__ecereMethod_")], (s = CopySystemPath(frame.file)), frame.line);
2842 else if(!strncmp(frame.func, "__ecereProp_", strlen("__ecereProp_")))
2843 ide.callStackView.Logf("%s Property, %s:%d\n", &frame.func[strlen("__ecereProp_")], (s = CopySystemPath(frame.file)), frame.line);
2844 else if(!strncmp(frame.func, "__ecereConstructor_", strlen("__ecereConstructor_")))
2845 ide.callStackView.Logf("%s Constructor, %s:%d\n", &frame.func[strlen("__ecereConstructor_")], (s = CopySystemPath(frame.file)), frame.line);
2846 else if(!strncmp(frame.func, "__ecereDestructor_", strlen("__ecereDestructor_")))
2847 ide.callStackView.Logf("%s Destructor, %s:%d\n", &frame.func[strlen("__ecereDestructor_")], (s = CopySystemPath(frame.file)), frame.line);
2849 ide.callStackView.Logf("%s Function, %s:%d\n", frame.func, (s = CopySystemPath(frame.file)), frame.line);
2854 ide.callStackView.Logf("%3d ", frame.level);
2859 ide.callStackView.Logf("inside %s, %s\n", frame.func, (s = CopySystemPath(frame.from)));
2863 ide.callStackView.Logf("%s\n", frame.func);
2865 ide.callStackView.Logf("unknown source\n");
2869 DebuggerProtocolUnknown("Unknown stack content", item.name);
2872 if(activeFrameLevel == -1)
2874 activeFrameLevel = 0;
2875 activeFrame = stackFrames.first;
2877 ide.callStackView.Home();
2879 subTokens.RemoveAll();
2881 /*else if(!strcmp(item.name, "frame"))
2884 item.value = StripCurlies(item.value);
2885 ParseFrame(&frame, item.value);
2887 else if(!strcmp(item.name, "thread-ids"))
2889 ide.threadsView.Clear();
2890 item.value = StripCurlies(item.value);
2891 TokenizeList(item.value, ',', subTokens);
2892 for(i = subTokens.count - 1; ; i--)
2894 if(TokenizeListItem(subTokens[i], item))
2896 if(!strcmp(item.name, "thread-id"))
2899 StripQuotes(item.value, item.value);
2900 value = atoi(item.value);
2901 ide.threadsView.Logf("%3d \n", value);
2904 DebuggerProtocolUnknown("Unknown threads content", item.name);
2909 ide.threadsView.Home();
2911 subTokens.RemoveAll();
2912 //if(!strcmp(outTokens[2], "number-of-threads"))
2914 else if(!strcmp(item.name, "new-thread-id"))
2916 StripQuotes(item.value, item.value);
2917 activeThread = atoi(item.value);
2919 else if(!strcmp(item.name, "value"))
2921 StripQuotes(item.value, item.value);
2922 eval.result = CopyString(item.value);
2923 eval.active = false;
2925 else if(!strcmp(item.name, "addr"))
2927 for(i = 2; i < outTokens.count; i++)
2929 if(TokenizeListItem(outTokens[i], item))
2931 if(!strcmp(item.name, "total-bytes"))
2933 StripQuotes(item.value, item.value);
2934 eval.bytes = atoi(item.value);
2936 else if(!strcmp(item.name, "next-row"))
2938 StripQuotes(item.value, item.value);
2939 eval.nextBlockAddress = strtoul(item.value, null, 0);
2941 else if(!strcmp(item.name, "memory"))
2945 //StripQuotes(item.value, item.value);
2946 item.value = StripBrackets(item.value);
2947 // this should be treated as a list...
2948 item.value = StripCurlies(item.value);
2949 TokenizeList(item.value, ',', subTokens);
2950 for(j = 0; j < subTokens.count; j++)
2952 if(TokenizeListItem(subTokens[j], item))
2954 if(!strcmp(item.name, "data"))
2956 item.value = StripBrackets(item.value);
2957 StripQuotes2(item.value, item.value);
2958 eval.result = CopyString(item.value);
2959 eval.active = false;
2963 subTokens.RemoveAll();
2968 else if(!strcmp(item.name, "source-path"))
2972 DebuggerProtocolUnknown("Unknown command reply", item.name);
2975 else if(!strcmp(outTokens[0], "^running"))
2977 waitingForPID = true;
2978 setWaitingForPID = true;
2980 else if(!strcmp(outTokens[0], "^exit"))
2983 ide.DebugUpdateMenus(loaded, false);
2984 // ide.outputView.debugBox.Logf("Exit\n");
2987 serialSemaphore.Release();
2989 else if(!strcmp(outTokens[0], "^error"))
2993 sentBreakInsert = false;
2996 printf("problem\n");
2998 bpItem = GdbDataBreakpoint { };
3001 if(outTokens.count > 1 && TokenizeListItem(outTokens[1], item))
3003 if(!strcmp(item.name, "msg"))
3005 StripQuotes(item.value, item.value);
3008 eval.active = false;
3010 if(strstr(item.value, "No symbol") && strstr(item.value, "in current context"))
3011 eval.error = symbolNotFound;
3012 else if(strstr(item.value, "Cannot access memory at address"))
3013 eval.error = memoryCantBeRead;
3015 eval.error = unknown;
3017 else if(!strcmp(item.value, "Previous frame inner to this frame (corrupt stack?)"))
3020 else if(!strncmp(item.value, "Cannot access memory at address", 31))
3023 else if(!strcmp(item.value, "Cannot find bounds of current function"))
3026 gdbHandle.Printf("-exec-continue\n");
3028 else if(!strcmp(item.value, "ptrace: No such process."))
3031 targetProcessId = 0;
3032 ide.DebugUpdateMenus(loaded, false);
3034 else if(!strcmp(item.value, "Function \\\"WinMain\\\" not defined."))
3037 else if(!strcmp(item.value, "You can't do that without a process to debug."))
3040 targetProcessId = 0;
3041 ide.DebugUpdateMenus(loaded, false);
3043 else if(strstr(item.value, "No such file or directory."))
3046 targetProcessId = 0;
3047 ide.DebugUpdateMenus(loaded, false);
3052 if(strlen(item.value) < MAX_F_STRING)
3055 ide.outputView.debugBox.Logf("GDB: %s\n", (s = CopyUnescapedString(item.value)));
3059 ide.outputView.debugBox.Logf("GDB: %s\n", item.value);
3065 DebuggerProtocolUnknown("Unknown error content", item.name);
3068 DebuggerProtocolUnknown("Unknown result-record", outTokens[0]);
3070 outTokens.RemoveAll();
3073 DebuggerProtocolUnknown("Unknown status-async-output", outTokens[0]);
3076 if(TokenizeList(output, ',', outTokens) && !strcmp(outTokens[0], "=thread-group-created")) //=thread-group-created,id="7611"
3078 else if(!strcmp(outTokens[0], "=thread-created")) //=thread-created,id="1",group-id="7611"
3080 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"
3083 DebuggerProtocolUnknown("Unknown notify-async-output", outTokens[0]);
3084 outTokens.RemoveAll();
3088 if(TokenizeList(output, ',', outTokens))
3090 if(!strcmp(outTokens[0],"*running"))
3092 waitingForPID = true;
3093 setWaitingForPID = true;
3095 else if(!strcmp(outTokens[0], "*stopped"))
3099 if(outTokens.count > 1 && TokenizeListItem(outTokens[1], item))
3101 if(!strcmp(item.name, "reason"))
3103 char * reason = item.value;
3104 StripQuotes(reason, reason);
3105 if(!strcmp(reason, "exited-normally") || !strcmp(reason, "exited") || !strcmp(reason, "exited-signalled"))
3108 if(outTokens.count > 2 && TokenizeListItem(outTokens[2], item2))
3110 StripQuotes(item2.value, item2.value);
3111 if(!strcmp(item2.name, "exit-code"))
3112 exitCode = item2.value;
3118 HandleExit(reason, exitCode);
3120 else if(!strcmp(reason, "breakpoint-hit"))
3124 printf("problem\n");
3126 stopItem = GdbDataStop { };
3128 for(i = 2; i < outTokens.count; i++)
3130 TokenizeListItem(outTokens[i], item);
3131 StripQuotes(item.value, item.value);
3132 if(!strcmp(item.name, "bkptno"))
3133 stopItem.bkptno = atoi(item.value);
3134 else if(!strcmp(item.name, "thread-id"))
3135 stopItem.threadid = atoi(item.value);
3136 else if(!strcmp(item.name, "frame"))
3138 item.value = StripCurlies(item.value);
3139 ParseFrame(stopItem.frame, item.value);
3142 DebuggerProtocolUnknown("Unknown breakpoint hit item name", item.name);
3147 else if(!strcmp(reason, "end-stepping-range"))
3151 printf("problem\n");
3153 stopItem = GdbDataStop { };
3155 for(i = 2; i < outTokens.count; i++)
3157 TokenizeListItem(outTokens[i], item);
3158 StripQuotes(item.value, item.value);
3159 if(!strcmp(item.name, "thread-id"))
3160 stopItem.threadid = atoi(item.value);
3161 else if(!strcmp(item.name, "frame"))
3163 item.value = StripCurlies(item.value);
3164 ParseFrame(stopItem.frame, item.value);
3166 else if(!strcmp(item.name, "reason"))
3168 else if(!strcmp(item.name, "bkptno"))
3171 DebuggerProtocolUnknown("Unknown end of stepping range item name", item.name);
3175 ide.DebugUpdateMenus(stopped, false);
3178 else if(!strcmp(reason, "function-finished"))
3182 printf("problem\n");
3184 stopItem = GdbDataStop { };
3185 stopItem.reason = CopyString(reason);
3187 for(i = 2; i < outTokens.count; i++)
3189 TokenizeListItem(outTokens[i], item);
3190 StripQuotes(item.value, item.value);
3191 if(!strcmp(item.name, "thread-id"))
3192 stopItem.threadid = atoi(item.value);
3193 else if(!strcmp(item.name, "frame"))
3195 item.value = StripCurlies(item.value);
3196 ParseFrame(stopItem.frame, item.value);
3198 else if(!strcmp(item.name, "gdb-result-var"))
3199 stopItem.gdbResultVar = CopyString(item.value);
3200 else if(!strcmp(item.name, "return-value"))
3201 stopItem.returnValue = CopyString(item.value);
3203 DebuggerProtocolUnknown("Unknown function finished item name", item.name);
3206 event = functionEnd;
3207 ide.DebugUpdateMenus(stopped, false);
3210 else if(!strcmp(reason, "signal-received"))
3214 printf("problem\n");
3216 stopItem = GdbDataStop { };
3217 stopItem.reason = CopyString(reason);
3219 for(i = 2; i < outTokens.count; i++)
3221 TokenizeListItem(outTokens[i], item);
3222 StripQuotes(item.value, item.value);
3223 if(!strcmp(item.name, "signal-name"))
3224 stopItem.name = CopyString(item.value);
3225 else if(!strcmp(item.name, "signal-meaning"))
3226 stopItem.meaning = CopyString(item.value);
3227 else if(!strcmp(item.name, "thread-id"))
3228 stopItem.threadid = atoi(item.value);
3229 else if(!strcmp(item.name, "frame"))
3231 item.value = StripCurlies(item.value);
3232 ParseFrame(stopItem.frame, item.value);
3235 DebuggerProtocolUnknown("Unknown signal reveived item name", item.name);
3237 if(!strcmp(stopItem.name, "SIGTRAP"))
3248 ide.DebugUpdateMenus(stopped, false);
3256 ide.DebugUpdateMenus(stopped, false);
3260 else if(!strcmp(reason, "watchpoint-trigger"))
3261 DebuggerProtocolUnknown("Reason watchpoint trigger not handled", "");
3262 else if(!strcmp(reason, "read-watchpoint-trigger"))
3263 DebuggerProtocolUnknown("Reason read watchpoint trigger not handled", "");
3264 else if(!strcmp(reason, "access-watchpoint-trigger"))
3265 DebuggerProtocolUnknown("Reason access watchpoint trigger not handled", "");
3266 else if(!strcmp(reason, "watchpoint-scope"))
3267 DebuggerProtocolUnknown("Reason watchpoint scope not handled", "");
3268 else if(!strcmp(reason, "location-reached"))
3269 DebuggerProtocolUnknown("Reason location reached not handled", "");
3271 DebuggerProtocolUnknown("Unknown reason", reason);
3278 DebuggerProtocolUnknown("Unknown exec-async-output", outTokens[0]);
3279 outTokens.RemoveAll();
3282 if(!strcmpi(output, "(gdb) "))
3286 char exeFile[MAX_LOCATION];
3287 int oldProcessID = targetProcessId;
3288 GetLastDirectory(targetFile, exeFile);
3292 targetProcessId = Process_GetChildExeProcessId(gdbProcessId, exeFile);
3293 if(targetProcessId || gdbHandle.Peek()) break;
3300 ide.DebugUpdateMenus(running, false);
3303 else if(!oldProcessID)
3305 ide.outputView.debugBox.Logf("Debugger Error: No target process ID\n");
3306 // TO VERIFY: The rest of this block has not been thoroughly tested in this particular location
3307 gdbHandle.Printf("-gdb-exit\n");
3309 state = terminated; //loaded;
3314 for(bp : ide.workspace.breakpoints)
3315 bp.inserted = false;
3318 bp.inserted = false;
3320 bpRunToCursor.inserted = false;
3322 ide.outputView.debugBox.Logf("Debugging stopped\n");
3323 ClearBreakDisplay();
3324 ide.DebugUpdateMenus(loaded, false);
3327 #if defined(__unix__)
3328 if(FileExists(progFifoPath)) //fileCreated)
3330 progThread.terminate = true;
3333 fifoFile.CloseInput();
3340 DeleteFile(progFifoPath);
3341 progFifoPath[0] = '\0';
3348 serialSemaphore.Release();
3351 DebuggerProtocolUnknown("Unknown prompt", output);
3355 if(!strncmp(output, "&\"warning:", 10))
3358 content = strstr(output, "\"");
3359 StripQuotes(content, content);
3360 content = strstr(content, ":");
3366 ide.outputView.debugBox.LogRaw((s = CopyUnescapedString(content)));
3373 DebuggerProtocolUnknown("Unknown output", output);
3375 if(!setWaitingForPID)
3376 waitingForPID = false;
3377 setWaitingForPID = false;
3385 void RunToCursorPrepare(char * absoluteFilePath, char * relativeFilePath, int lineNumber)
3389 //bpRunToCursor.Free();
3390 bpRunToCursor = Breakpoint { };
3393 bpRunToCursor = Breakpoint { };
3395 if(absoluteFilePath)
3396 bpRunToCursor.absoluteFilePath = CopyString(absoluteFilePath);
3397 if(relativeFilePath)
3398 bpRunToCursor.relativeFilePath = CopyString(relativeFilePath);
3399 bpRunToCursor.line = lineNumber;
3400 bpRunToCursor.type = runToCursor;
3401 bpRunToCursor.enabled = true;
3402 bpRunToCursor.condition = null;
3403 bpRunToCursor.ignore = 0;
3404 bpRunToCursor.level = -1;
3407 ExpressionType ::DebugEvalExpTypeError(char * result)
3413 case symbolNotFound:
3414 return symbolErrorExp;
3415 case memoryCantBeRead:
3416 return memoryErrorExp;
3418 return unknownErrorExp;
3421 char * ::EvaluateExpression(char * expression, ExpressionType * error)
3424 if(ide.projectView && ide.debugger.state == stopped)
3426 result = GdbEvaluateExpression(expression);
3427 *error = DebugEvalExpTypeError(result);
3432 *error = noDebuggerErrorExp;
3437 char * ::ReadMemory(uint address, int size, char format, ExpressionType * error)
3440 char * result = GdbReadMemoryString(address, size, format, 1, 1);
3441 if(!result || !strcmp(result, "N/A"))
3442 *error = memoryErrorExp;
3444 *error = DebugEvalExpTypeError(result);
3449 class GdbThread : Thread
3455 static char output[4096];
3456 Array<char> dynamicBuffer { minAllocSize = 4096 };
3457 DualPipe oldGdbHandle = gdbHandle;
3458 incref oldGdbHandle;
3461 while(debugger.state != terminated && gdbHandle && !gdbHandle.Eof())
3465 result = gdbHandle.Read(output, 1, sizeof(output));
3466 if(debugger.state == terminated || !gdbHandle || gdbHandle.Eof())
3474 for(c = 0; c<result; c++)
3476 if(output[c] == '\n')
3478 int pos = dynamicBuffer.size;
3479 dynamicBuffer.size += c - start;
3480 memcpy(&dynamicBuffer[pos], output + start, c - start);
3481 if(dynamicBuffer.count && dynamicBuffer[dynamicBuffer.count - 1] != '\r')
3482 // COMMENTED OUT DUE TO ISSUE #135, FIXED
3483 //if(dynamicBuffer.array[dynamicBuffer.count - 1] != '\r')
3484 dynamicBuffer.size++;
3485 dynamicBuffer[dynamicBuffer.count - 1] = '\0';
3487 // printf("%s\n", dynamicBuffer.array);
3489 debugger.GdbThreadMain(&dynamicBuffer[0]);
3490 dynamicBuffer.size = 0;
3496 int pos = dynamicBuffer.size;
3497 dynamicBuffer.size += c - start;
3498 memcpy(&dynamicBuffer[pos], output + start, c - start);
3504 printf("Got end of file from GDB!\n");
3508 delete dynamicBuffer;
3509 //if(oldGdbHandle == gdbHandle)
3510 debugger.GdbThreadExit();
3511 delete oldGdbHandle;
3517 #if defined(__unix__)
3522 #include <sys/types.h>
3527 class ProgramThread : Thread
3533 bool fileCreated = false;
3535 static char output[1000];
3538 /*if(!mkfifo(progFifoPath, mask))
3545 ide.outputView.debugBox.Logf("err: Unable to create FIFO %s\n", progFifoPath);
3549 if(FileExists(progFifoPath)) //fileCreated)
3551 fifoFile = FileOpen(progFifoPath, read);
3555 ide.outputView.debugBox.Logf("err: Unable to open FIFO %s for read\n", progFifoPath);
3564 fd = fileno(fifoFile.input);
3566 //fcntl(fd, F_SETFL, fcntl(fd, F_GETFL) | O_NONBLOCK);
3570 while(!terminate && fifoFile && !fifoFile.Eof())
3573 struct timeval time;
3581 selectResult = select(fd + 1, &rs, null, null, &time);
3582 if(FD_ISSET(fd, &rs))
3584 int result = read(fd, output, sizeof(output)-1);
3585 if(!result || (result < 0 && errno != EAGAIN))
3589 output[result] = '\0';
3590 if(strcmp(output,"&\"warning: GDB: Failed to set controlling terminal: Invalid argument\\n\"\n"))
3593 ide.outputView.debugBox.Log(output);
3602 //fifoFile.CloseInput();
3605 ide.outputView.debugBox.Log("\n");
3609 if(FileExists(progFifoPath)) //fileCreated)
3611 DeleteFile(progFifoPath);
3612 progFifoPath[0] = '\0';
3620 class Argument : struct
3622 Argument prev, next;
3638 class Frame : struct
3647 property char * from { set { delete from; if(value) from = CopyUnescapedUnixPath(value); } }
3649 property char * file { set { delete file; if(value) file = CopyUnescapedUnixPath(value); } }
3650 char * absoluteFile;
3659 delete absoluteFile;
3660 args.Free(Argument::Free);
3669 class GdbDataStop : struct
3686 char * gdbResultVar;
3696 if(!strcmp(reason, "signal-received"))
3701 else if(!strcmp(reason, "function-finished"))
3703 delete gdbResultVar;
3708 if(frame) frame.Free();
3717 class GdbDataBreakpoint : struct
3726 property char * file { set { delete file; if(value) file = CopyUnescapedUnixPath(value); } }
3741 ~GdbDataBreakpoint()
3747 class Breakpoint : struct
3751 char * relativeFilePath;
3752 char * absoluteFilePath;
3760 BreakpointType type;
3763 GdbDataBreakpoint bp;
3765 char * LocationToString()
3767 char location[MAX_LOCATION+20];
3768 sprintf(location, "%s:%d", relativeFilePath, line);
3769 #if defined(__WIN32__)
3770 ChangeCh(location, '/', '\\');
3772 return CopyString(location);
3777 if(relativeFilePath && relativeFilePath[0])
3779 f.Printf(" * %d,%d,%d,%d,%s\n", enabled ? 1 : 0, ignore, level, line, relativeFilePath);
3781 f.Printf(" ~ %s\n", condition.expression);
3790 delete relativeFilePath;
3791 delete absoluteFilePath;
3801 class Watch : struct
3812 f.Printf(" ~ %s\n", expression);
3836 class DebugListItem : struct
3842 struct DebugEvaluationData
3847 uint nextBlockAddress;
3849 DebuggerEvaluationError error;
3852 class CodeLocation : struct
3855 char * absoluteFile;
3858 CodeLocation ::ParseCodeLocation(char * location)
3862 char * colon = null;
3864 char loc[MAX_LOCATION];
3865 strcpy(loc, location);
3866 for(temp = loc; temp = strstr(temp, ":"); temp++)
3874 int line = atoi(colon);
3877 CodeLocation codloc { line = line };
3878 codloc.file = CopyString(loc);
3879 codloc.absoluteFile = ide.workspace.GetAbsolutePathFromRelative(loc);
3891 delete absoluteFile;