6 //#define GDB_DEBUG_CONSOLE
8 extern char * strrchr(char * s, char c);
20 #include <sys/time.h> // Required on Apple...
24 //bool eString_PathInsidePath(char * to, char * path)
25 bool eString_PathInsideOf(char * path, char * of)
27 if(!path[0] || !of[0])
28 return false; // What to do here? Ever used?
31 char ofPart[MAX_FILENAME], ofRest[MAX_LOCATION];
32 char pathPart[MAX_FILENAME], pathRest[MAX_LOCATION];
34 strcpy(pathRest, path);
35 for(; ofRest[0] && pathRest[0];)
37 SplitDirectory(ofRest, ofPart, ofRest);
38 SplitDirectory(pathRest, pathPart, pathRest);
39 if(fstrcmp(pathPart, ofPart))
42 if(!ofRest[0] && !pathRest[0]) // paths are identical - should return false or true? (changed to false)
44 else if(!pathRest[0]) // not inside of, it's the other way around
50 public char * StripQuotes2(char * string, char * output)
54 bool quoted = false, escaped = false;
56 for(c = 0; ch = string[c]; c++)
60 if(escaped || ch != '\"')
79 static void strescpy(char * d, char * s)
132 static char * CopyUnescapedSystemPath(char * p)
134 char * d = new char[strlen(p) + 1];
136 #if defined(__WIN32__)
137 ChangeCh(d, '/', '\\');
142 static char * CopyUnescapedUnixPath(char * p)
144 char * d = new char[strlen(p) + 1];
146 #if defined(__WIN32__)
147 ChangeCh(d, '\\', '/');
152 static char * CopyUnescapedString(char * s)
154 char * d = new char[strlen(s) + 1];
159 // String Unescape Copy
161 // TOFIX: THIS DOESN'T HANDLE NUMERIC ESCAPE CODES (OCTAL/HEXADECIMAL...)?
162 // Seems very similar to ReadString in pass15.ec (which also misses numeric escape codes :) )
164 static void struscpy(char * d, char * s)
216 static char * StripBrackets(char * string)
218 int length = strlen(string);
219 if(length > 1 && *string == '[' && string[length - 1] == ']')
222 string[length - 1] = '\0';
229 static char * StripCurlies(char * string)
231 int length = strlen(string);
232 if(length > 1 && *string == '{' && string[length - 1] == '}')
235 string[length - 1] = '\0';
242 static int StringGetInt(char * string, int start)
245 int i, len = strlen(string);
247 for(i = start; i < len && i < start + 8; i++)
249 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')
250 strncat(number, &string[i], 1);
257 static int TokenizeList(char * string, const char seperator, Array<char *> tokens)
261 bool quoted = false; //bool escaped = false;
262 char * start = string;
264 for(; *string; string++)
273 else if(*string == '\"')
275 else if(*string == '{' || *string == '[' || *string == '(' || *string == '<')
277 else if(*string == '}' || *string == ']' || *string == ')' || *string == '>')
279 else if(*string == seperator && !level)
288 //tokens[count] = start;
289 //tokens[count++] = start;
296 static bool TokenizeListItem(char * string, DebugListItem item)
298 char * equal = strstr(string, "=");
312 static void DebuggerProtocolUnknown(char * message, char * gdbOutput)
314 #ifdef _DEBUG_GDB_PROTOCOL
315 ide.outputView.debugBox.Logf("Debugger Protocol Error: %s (%s)\n", message, gdbOutput);
319 // define GdbGetLineSize = 1638400;
320 define GdbGetLineSize = 5638400;
321 #if defined(__unix__)
322 char progFifoPath[MAX_LOCATION];
323 char progFifoDir[MAX_LOCATION];
326 enum DebuggerState { none, prompt, loaded, running, stopped, terminated };
327 enum DebuggerEvent { none, hit, breakEvent, signal, stepEnd, functionEnd, exit };
328 enum DebuggerAction { none, internal, restart, stop, selectFrame }; //, bpValidation
329 enum BreakpointType { none, internalMain, internalWinMain, internalModulesLoaded, user, runToCursor };
330 enum DebuggerEvaluationError { none, symbolNotFound, memoryCantBeRead, unknown };
332 FileDialog debuggerFileDialog { type = selectDir };
334 static DualPipe gdbHandle;
335 static DebugEvaluationData eval { };
337 static int targetProcessId;
339 static bool gdbReady;
343 Semaphore serialSemaphore { };
348 //bool breakpointsInserted;
350 bool sentBreakInsert;
351 bool ignoreBreakpoints;
352 bool userBreakOnInternBreak;
359 int activeFrameLevel;
370 DebuggerAction breakType;
371 //DebuggerCommand lastCommand; // THE COMPILER COMPILES STUFF THAT DOES NOT EXIST???
373 GdbDataStop stopItem;
374 GdbDataBreakpoint bpItem;
377 List<Breakpoint> sysBPs { };
378 Breakpoint bpRunToCursor;
384 ProjectConfig prjConfig;
386 CodeEditor codeEditor;
388 GdbThread gdbThread { debugger = this };
391 delay = 0.0, userData = this;
395 bool monitor = false;
396 DebuggerEvent curEvent = event;
397 GdbDataStop stopItem = this.stopItem;
403 this.stopItem = null;
406 if(curEvent && curEvent != exit)
409 printf("No stop item\n");
427 GdbCommand(false, "-stack-select-frame %d", activeFrameLevel);
428 for(activeFrame = stackFrames.first; activeFrame; activeFrame = activeFrame.next)
429 if(activeFrame.level == activeFrameLevel)
435 // GdbCommand(false, "-break-info %d", bpItem.number);
445 activeThread = stopItem.threadid;
446 GdbCommand(false, "-thread-list-ids");
451 Breakpoint bp = null;
453 for(i : ide.workspace.breakpoints; i.bp && i.bp.number == stopItem.bkptno)
460 for(i : sysBPs; i.bp && i.bp.number == stopItem.bkptno)
468 if(!(!userBreakOnInternBreak &&
469 bp && (bp.type == internalMain || bp.type == internalWinMain || bp.type == internalModulesLoaded)))
471 hitThread = stopItem.threadid;
475 signalThread = stopItem.threadid;
487 activeThread = stopItem.threadid;
488 GdbCommand(false, "-thread-list-ids");
490 if(activeFrameLevel > 0)
491 GdbCommand(false, "-stack-select-frame %d", activeFrameLevel);
493 WatchesCodeEditorLinkInit();
503 ide.outputView.debugBox.Logf("Signal received: %s - %s\n", stopItem.name, stopItem.meaning);
504 ide.outputView.debugBox.Logf(" %s:%d\n", (s = CopySystemPath(stopItem.frame.file)), stopItem.frame.line);
510 // Why was SelectFrame missing here?
511 SelectFrame(activeFrameLevel);
512 GoToStackFrameLine(activeFrameLevel, curEvent == signal || curEvent == stepEnd /*false*/);
515 if(curEvent == signal)
516 ide.outputView.Show();
517 if(curEvent == signal || curEvent == breakEvent)
519 if(curEvent == breakEvent)
520 ide.threadsView.Show();
521 ide.callStackView.Show();
523 ide.ShowCodeEditor();
524 if(curEvent == breakEvent)
525 ide.callStackView.Activate();
532 if(curEvent == DebuggerEvent::breakEvent || curEvent == stepEnd || curEvent == functionEnd)
533 ignoreBreakpoints = false;
544 #ifdef GDB_DEBUG_CONSOLE
545 char lastGdbOutput[GdbGetLineSize];
547 #if defined(__unix__)
548 ProgramThread progThread { };
551 void ChangeState(DebuggerState value)
554 if(ide) ide.AdjustDebugMenus();
559 // Stop(); // Don't need to call Stop here, because ~ProjectView() will call it explicitly.
561 stackFrames.Free(Frame::Free);
571 waitingForPID = false;
576 sentBreakInsert = false;
577 ignoreBreakpoints = false;
578 userBreakOnInternBreak = false;
581 activeFrameLevel = 0;
598 bpRunToCursor = null;
604 /*GdbThread gdbThread
610 ideProcessId = Process_GetCurrentProcessId();
612 sysBPs.Add(Breakpoint { type = internalMain, enabled = true, level = -1 });
613 #if defined(__WIN32__)
614 sysBPs.Add(Breakpoint { type = internalWinMain, enabled = true, level = -1 });
616 sysBPs.Add(Breakpoint { type = internalModulesLoaded, enabled = true, level = -1 });
629 property bool isActive { get { return state == running || state == stopped; } }
630 property bool isPrepared { get { return state == loaded || state == running || state == stopped; } }
634 GdbExecContinue(true);
643 //ide.AdjustDebugMenus();
644 GdbDebugBreak(false);
657 GdbDebugBreak(false);
676 GdbDebugBreak(false);
691 bool GoToCodeLine(char * location)
694 codloc = CodeLocation::ParseCodeLocation(location);
697 CodeEditor editor = (CodeEditor)ide.OpenFile(codloc.absoluteFile, normal, true, null, no, normal);
700 EditBox editBox = editor.editBox;
701 editBox.GoToLineNum(codloc.line - 1);
702 editBox.GoToPosition(editBox.line, codloc.line - 1, 0);
709 bool GoToStackFrameLine(int stackLevel, bool askForLocation)
713 char filePath[MAX_LOCATION];
714 char sourceDir[MAX_LOCATION];
716 CodeEditor editor = null;
717 if(stackLevel == -1) // this (the two lines) is part of that fix that I would not put in for some time
719 for(frame = stackFrames.first; frame; frame = frame.next)
720 if(frame.level == stackLevel)
724 ide.callStackView.Show();
726 if(!frame.absoluteFile && frame.file)
727 frame.absoluteFile = ide.workspace.GetAbsolutePathFromRelative(frame.file);
728 if(!frame.absoluteFile && askForLocation && frame.file)
731 char title[MAX_LOCATION];
733 sprintf(title, "Provide source file location for %s", (s = CopySystemPath(frame.file)));
735 if(SourceDirDialog(title, ide.workspace.projectDir, frame.file, sourceDir))
737 AddSourceDir(sourceDir);
738 frame.absoluteFile = ide.workspace.GetAbsolutePathFromRelative(frame.file);
741 if(frame.absoluteFile)
742 editor = (CodeEditor)ide.OpenFile(frame.absoluteFile, normal, true, null, no, normal);
744 if(editor && frame.line)
746 EditBox editBox = editor.editBox;
747 editBox.GoToLineNum(frame.line - 1);
748 editBox.GoToPosition(editBox.line, frame.line - 1, 0);
756 void SelectThread(int thread)
760 if(thread != activeThread)
762 activeFrameLevel = -1;
763 ide.callStackView.Clear();
764 GdbCommand(false, "-thread-select %d", thread);
766 // Why was SelectFrame missing here?
767 SelectFrame(activeFrameLevel);
768 GoToStackFrameLine(activeFrameLevel, true);
769 WatchesCodeEditorLinkRelease();
770 WatchesCodeEditorLinkInit();
774 ide.callStackView.Show();
778 void SelectFrame(int frame)
782 if(frame != activeFrameLevel || !codeEditor || !codeEditor.visible)
784 activeFrameLevel = frame; // there is no active frame number in the gdb reply
785 GdbCommand(false, "-stack-select-frame %d", activeFrameLevel);
786 for(activeFrame = stackFrames.first; activeFrame; activeFrame = activeFrame.next)
787 if(activeFrame.level == activeFrameLevel)
790 WatchesCodeEditorLinkRelease();
791 WatchesCodeEditorLinkInit();
798 void HandleExit(char * reason, char * code)
800 bool returnedExitCode = false;
801 char verboseExitCode[128];
803 ChangeState(loaded); // this state change seems to be superfluous, might be in case of gdb crash
807 sprintf(verboseExitCode, " with exit code %s", code);
809 verboseExitCode[0] = '\0';
813 // ClearBreakDisplay();
817 for(wh : ide.workspace.watches)
819 if(wh.type) FreeType(wh.type);
822 ide.watchesView.UpdateWatch(wh);
826 //ide.AdjustDebugMenus();
828 #if defined(__unix__)
829 progThread.terminate = true;
832 fifoFile.CloseInput();
841 char program[MAX_LOCATION];
842 GetSystemPathBuffer(program, targetFile);
844 ide.outputView.debugBox.Logf("The program %s has exited%s.\n", program, verboseExitCode);
845 else if(!strcmp(reason, "exited-normally"))
846 ide.outputView.debugBox.Logf("The program %s has exited normally%s.\n", program, verboseExitCode);
847 else if(!strcmp(reason, "exited"))
848 ide.outputView.debugBox.Logf("The program %s has exited%s.\n", program, verboseExitCode);
849 else if(!strcmp(reason, "exited-signalled"))
850 ide.outputView.debugBox.Logf("The program %s has exited with a signal%s.\n", program, verboseExitCode);
852 ide.outputView.debugBox.Logf("The program %s has exited (gdb provided an unknown reason)%s.\n", program, verboseExitCode);
859 ide.outputView.debugBox.Clear();
881 ide.outputView.ShowClearSelectTab(debug);
882 ide.outputView.debugBox.Logf("Starting debug mode\n");
883 userBreakOnInternBreak = true;
892 void StepOver(bool ignoreBkpts)
901 ide.outputView.ShowClearSelectTab(debug);
902 ide.outputView.debugBox.Logf("Starting debug mode\n");
903 ignoreBreakpoints = ignoreBkpts;
904 userBreakOnInternBreak = true;
908 ignoreBreakpoints = ignoreBkpts;
909 if(ignoreBreakpoints)
910 GdbBreakpointsDelete(true);
916 void StepOut(bool ignoreBkpts)
920 ignoreBreakpoints = ignoreBkpts;
921 if(ignoreBreakpoints)
922 GdbBreakpointsDelete(true);
927 void RunToCursor(char * absoluteFilePath, int lineNumber, bool ignoreBkpts)
929 char relativeFilePath[MAX_LOCATION];
930 DebuggerState oldState = state;
931 ignoreBreakpoints = ignoreBkpts;
932 if(!ide.projectView.GetRelativePath(absoluteFilePath, relativeFilePath))
933 strcpy(relativeFilePath, absoluteFilePath);
945 ide.outputView.ShowClearSelectTab(debug);
946 ide.outputView.debugBox.Logf("Starting debug mode\n");
948 RunToCursorPrepare(absoluteFilePath, relativeFilePath, lineNumber);
949 sentBreakInsert = true;
950 GdbCommand(false, "-break-insert %s:%d", relativeFilePath, lineNumber);
951 bpRunToCursor.bp = bpItem;
953 bpRunToCursor.inserted = (bpRunToCursor.bp.number != 0);
954 ValidateBreakpoint(bpRunToCursor);
961 if(ignoreBreakpoints)
962 GdbBreakpointsDelete(false);
966 if(ignoreBreakpoints)
967 GdbBreakpointsDelete(false);
968 GdbExecContinue(true);
974 void GetCallStackCursorLine(bool * error, int * lineCursor, int * lineTopFrame)
976 if(activeFrameLevel == -1)
984 *error = signalOn && activeThread == signalThread;
985 *lineCursor = activeFrameLevel + 1;
986 *lineTopFrame = activeFrameLevel ? 1 : 0;
990 int GetMarginIconsLineNumbers(char * fileName, int lines[], bool enabled[], int max, bool * error, int * lineCursor, int * lineTopFrame)
992 char winFilePath[MAX_LOCATION];
993 char * absoluteFilePath = GetSlashPathBuffer(winFilePath, fileName);
995 Iterator<Breakpoint> it { ide.workspace.breakpoints };
996 while(it.Next() && count < max)
998 Breakpoint bp = it.data;
1001 if(bp.absoluteFilePath && bp.absoluteFilePath[0] && !fstrcmp(bp.absoluteFilePath, absoluteFilePath))
1003 lines[count] = bp.line;
1004 enabled[count] = bp.enabled;
1009 if(activeFrameLevel == -1)
1017 *error = signalOn && activeThread == signalThread;
1018 if(activeFrame && activeFrame.absoluteFile && !fstrcmp(absoluteFilePath, activeFrame.absoluteFile))
1019 *lineCursor = activeFrame.line;
1022 if(activeFrame && stopItem && stopItem.frame && activeFrame.level == stopItem.frame.level)
1024 else if(stopItem && stopItem.frame && stopItem.frame.absoluteFile && !fstrcmp(absoluteFilePath, stopItem.frame.absoluteFile))
1025 *lineTopFrame = stopItem.frame.line;
1029 if(*lineTopFrame == *lineCursor && *lineTopFrame)
1035 void ChangeWatch(DataRow row, char * expression)
1037 Watch wh = (Watch)row.tag;
1040 delete wh.expression;
1042 wh.expression = CopyString(expression);
1045 Iterator<Watch> it { ide.workspace.watches };
1047 ide.workspace.watches.Delete(it.pointer);
1054 ide.workspace.watches.Add(wh);
1056 wh.expression = CopyString(expression);
1058 ide.workspace.Save();
1059 //if(expression && state == stopped)
1064 void MoveIcons(char * fileName, int lineNumber, int move, bool start)
1066 char winFilePath[MAX_LOCATION];
1067 char * absoluteFilePath = GetSlashPathBuffer(winFilePath, fileName);
1070 for(bpLink = ide.workspace.breakpoints.first; bpLink; bpLink = next)
1072 Breakpoint bp = (Breakpoint)bpLink.data;
1075 if(bp.type == user && bp.absoluteFilePath && !fstrcmp(bp.absoluteFilePath, absoluteFilePath))
1077 if(bp.line > lineNumber || (bp.line == lineNumber && start))
1079 if(move < 0 && (bp.line < lineNumber - move))
1080 ide.workspace.RemoveBreakpoint(bp);
1084 ide.breakpointsView.UpdateBreakpoint(bp.row);
1085 ide.workspace.Save();
1091 // moving code cursors is futile, on next step, stop, hit, cursors will be offset anyways
1094 bool SourceDirDialog(char * title, char * startDir, char * test, char * sourceDir)
1098 String srcDir = null;
1100 debuggerFileDialog.text = title;
1101 debuggerFileDialog.currentDirectory = startDir;
1102 debuggerFileDialog.master = ide;
1104 while(debuggerFileDialog.Modal())
1106 strcpy(sourceDir, debuggerFileDialog.filePath);
1107 if(!fstrcmp(ide.workspace.projectDir, sourceDir) &&
1108 MessageBox { type = yesNo, master = ide,
1109 contents = "This is the project directory.\nWould you like to try again?",
1110 text = "Invalid Source Directory" }.Modal() == no)
1114 for(dir : ide.workspace.sourceDirs)
1116 if(!fstrcmp(dir, sourceDir))
1124 MessageBox { type = yesNo, master = ide,
1125 contents = "This source directory is already specified.\nWould you like to try again?",
1126 text = "Invalid Source Directory" }.Modal() == no)
1132 char file[MAX_LOCATION];
1133 strcpy(file, sourceDir);
1134 PathCat(file, test);
1135 result = FileExists(file);
1137 MessageBox { type = yesNo, master = ide,
1138 contents = "Unable to locate source file.\nWould you like to try again?",
1139 text = "Invalid Source Directory" }.Modal() == no)
1153 void AddSourceDir(char * sourceDir)
1155 ide.workspace.sourceDirs.Add(CopyString(sourceDir));
1156 ide.workspace.Save();
1160 DebuggerState oldState = state;
1165 GdbDebugBreak(true);
1168 GdbCommand(false, "-environment-directory \"%s\"", sourceDir);
1171 if(oldState == running)
1172 GdbExecContinue(false);
1176 void ToggleBreakpoint(char * fileName, int lineNumber, Project prj)
1178 char winFilePath[MAX_LOCATION];
1179 char * absoluteFilePath = GetSlashPathBuffer(winFilePath, fileName);
1180 char absolutePath[MAX_LOCATION];
1181 char relativePath[MAX_LOCATION];
1182 char sourceDir[MAX_LOCATION];
1183 Breakpoint bp = null;
1185 strcpy(absolutePath, absoluteFilePath);
1186 for(i : ide.workspace.breakpoints; i.type == user && i.absoluteFilePath && !fstrcmp(i.absoluteFilePath, absolutePath) && i.line == lineNumber)
1195 ide.workspace.RemoveBreakpoint(bp);
1203 // FIXED: This is how it should have been... Source locations are only for files not in project
1204 // if(eString_PathInsideOf(absolutePath, ide.workspace.projectDir))
1205 // MakePathRelative(absolutePath, ide.workspace.projectDir, relativePath);
1206 bool result = false;
1208 result = prj.GetRelativePath(absolutePath, relativePath);
1210 ide.projectView.GetRelativePath(absolutePath, relativePath);
1211 //if(ide.projectView.GetRelativePath(absolutePath, relativePath));
1215 char title[MAX_LOCATION];
1216 char directory[MAX_LOCATION];
1217 StripLastDirectory(absolutePath, directory);
1218 sprintf(title, "Provide source files location directory for %s", absolutePath);
1221 String srcDir = null;
1222 for(dir : ide.workspace.sourceDirs)
1224 if(eString_PathInsideOf(absolutePath, dir))
1226 MakePathRelative(absoluteFilePath, dir, relativePath);
1234 if(SourceDirDialog(title, directory, null, sourceDir))
1236 if(eString_PathInsideOf(absolutePath, sourceDir))
1238 AddSourceDir(sourceDir);
1239 MakePathRelative(absoluteFilePath, sourceDir, relativePath);
1242 else if(MessageBox { type = yesNo, master = ide,
1243 contents = "You must provide a valid source directory in order to place a breakpoint in this file.\nWould you like to try again?",
1244 text = "Invalid Source Directory" }.Modal() == no)
1247 else if(MessageBox { type = yesNo, master = ide,
1248 contents = "You must provide a source directory in order to place a breakpoint in this file.\nWould you like to try again?",
1249 text = "No Source Directory Provided" }.Modal() == no)
1253 ide.workspace.bpCount++;
1254 bp = { line = lineNumber, type = user, enabled = true, level = -1 };
1255 ide.workspace.breakpoints.Add(bp);
1256 bp.absoluteFilePath = CopyString(absolutePath);
1257 bp.relativeFilePath = CopyString(relativePath);
1258 ide.breakpointsView.AddBreakpoint(bp);
1263 DebuggerState oldState = state;
1268 GdbDebugBreak(true);
1273 sentBreakInsert = true;
1274 GdbCommand(false, "-break-insert %s:%d", bp.relativeFilePath, bp.line);
1277 bp.inserted = (bp.bp && bp.bp.number != 0);
1278 ValidateBreakpoint(bp);
1282 if(oldState == running)
1283 GdbExecContinue(false);
1286 ide.workspace.Save();
1289 void UpdateRemovedBreakpoint(Breakpoint bp)
1291 if(targeted && bp.inserted)
1293 DebuggerState oldState = state;
1298 GdbDebugBreak(true);
1302 GdbCommand(false, "-break-delete %d", bp.bp.number);
1305 if(oldState == running)
1306 GdbExecContinue(false);
1312 void ParseFrame(Frame frame, char * string)
1315 Array<char *> frameTokens { minAllocSize = 50 };
1316 Array<char *> argsTokens { minAllocSize = 50 };
1317 Array<char *> argumentTokens { minAllocSize = 50 };
1318 DebugListItem item { };
1321 TokenizeList(string, ',', frameTokens);
1322 for(i = 0; i < frameTokens.count; i++)
1324 if(TokenizeListItem(frameTokens[i], item))
1326 StripQuotes(item.value, item.value);
1327 if(!strcmp(item.name, "level"))
1328 frame.level = atoi(item.value);
1329 else if(!strcmp(item.name, "addr"))
1330 frame.addr = CopyString(item.value);
1331 else if(!strcmp(item.name, "func"))
1332 frame.func = CopyString(item.value);
1333 else if(!strcmp(item.name, "args"))
1335 if(!strcmp(item.value, "[]"))
1336 frame.argsCount = 0;
1339 item.value = StripBrackets(item.value);
1340 TokenizeList(item.value, ',', argsTokens);
1341 for(j = 0; j < argsTokens.count; j++)
1343 argsTokens[j] = StripCurlies(argsTokens[j]);
1344 TokenizeList(argsTokens[j], ',', argumentTokens);
1345 for(k = 0; k < argumentTokens.count; k++)
1348 frame.args.Add(arg);
1349 if(TokenizeListItem(argumentTokens[k], item))
1351 if(!strcmp(item.name, "name"))
1353 StripQuotes(item.value, item.value);
1354 arg.name = CopyString(item.value);
1356 else if(!strcmp(item.name, "value"))
1358 StripQuotes(item.value, item.value);
1359 arg.value = CopyString(item.value);
1362 DebuggerProtocolUnknown("Unknown frame args item name", item.name);
1365 DebuggerProtocolUnknown("Bad frame args item", "");
1367 argumentTokens.RemoveAll();
1369 frame.argsCount = argsTokens.count;
1370 argsTokens.RemoveAll();
1373 else if(!strcmp(item.name, "from"))
1374 frame.from = item.value;
1375 else if(!strcmp(item.name, "file"))
1377 frame.file = item.value;
1378 frame.absoluteFile = ide.workspace.GetAbsolutePathFromRelative(frame.file);
1380 else if(!strcmp(item.name, "line"))
1381 frame.line = atoi(item.value);
1382 else if(!strcmp(item.name, "fullname"))
1384 // New GDB is giving us a full name... Any reason why we coudln't figure it out ourselves?
1387 DebuggerProtocolUnknown("Unknown frame member name", item.name);
1390 DebuggerProtocolUnknown("Bad frame", "");
1395 delete argumentTokens;
1399 void ShowDebuggerViews()
1401 ide.outputView.Show();
1402 ide.outputView.SelectTab(debug);
1403 ide.threadsView.Show();
1404 ide.callStackView.Show();
1405 ide.watchesView.Show();
1409 void HideDebuggerViews()
1411 ide.RepositionWindows(true);
1414 void ::GdbCommand(bool focus, char * format, ...)
1418 char string[MAX_F_STRING];
1421 va_start(args, format);
1422 vsprintf(string, format, args);
1426 ide.debugger.serialSemaphore.TryWait();
1429 #ifdef GDB_DEBUG_CONSOLE
1430 Log(string); Log("\n");
1432 #ifdef GDB_DEBUG_OUTPUT
1433 ide.outputView.gdbBox.Logf("cmd: %s\n", string);
1435 #ifdef GDB_DEBUG_GUI
1437 ide.gdbDialog.AddCommand(string);
1439 gdbHandle.Printf("%s\n", string);
1442 Process_ShowWindows(targetProcessId);
1445 ide.debugger.serialSemaphore.Wait();
1450 bool ValidateBreakpoint(Breakpoint bp)
1454 if(bp.bp.line != bp.line)
1459 ide.outputView.debugBox.Logf("WOULD HAVE -- Invalid breakpoint disabled: %s:%d\n", bp.relativeFilePath, bp.line);
1463 //GdbCommand(false, "-break-delete %d", bp.bp.number);
1464 //bp.inserted = false;
1466 //bp.enabled = false;
1471 ide.outputView.debugBox.Logf("Debugger Error: ValidateBreakpoint error\n");
1472 bp.line = bp.bp.line;
1479 static void GdbInsertInternalBreakpoint()
1483 //if(!breakpointsInserted)
1485 DirExpression objDir = ide.project.objDir;
1490 if(bp.type == internalMain)
1492 sentBreakInsert = true;
1493 GdbCommand(false, "-break-insert main");
1496 bp.inserted = (bp.bp && bp.bp.number != 0);
1498 #if defined(__WIN32__)
1499 else if(bp.type == internalWinMain)
1501 sentBreakInsert = true;
1502 GdbCommand(false, "-break-insert WinMain");
1505 bp.inserted = (bp.bp && bp.bp.number != 0);
1508 else if(bp.type == internalModulesLoaded)
1510 char path[MAX_LOCATION];
1511 char name[MAX_LOCATION];
1512 char fixedModuleName[MAX_FILENAME];
1515 bool moduleLoadBlock = false;
1517 ReplaceSpaces(fixedModuleName, ide.project.moduleName);
1518 sprintf(name, "%s.main.ec", fixedModuleName);
1519 strcpy(path, ide.workspace.projectDir);
1520 PathCatSlash(path, objDir.dir);
1521 PathCatSlash(path, name);
1522 f = FileOpen(path, read);
1525 for(lineNumber = 1; !f.Eof(); lineNumber++)
1527 if(f.GetLine(line, sizeof(line) - 1))
1529 bool moduleLoadLine;
1530 TrimLSpaces(line, line);
1531 moduleLoadLine = !strncmp(line, "eModule_Load", strlen("eModule_Load"));
1532 if(!moduleLoadBlock && moduleLoadLine)
1533 moduleLoadBlock = true;
1534 else if(moduleLoadBlock && !moduleLoadLine && strlen(line) > 0)
1540 char relative[MAX_LOCATION];
1541 bp.absoluteFilePath = CopyString(path);
1542 MakePathRelative(path, ide.workspace.projectDir, relative);
1543 delete bp.relativeFilePath;
1544 bp.relativeFilePath = CopyString(relative);
1545 bp.line = lineNumber;
1546 sentBreakInsert = true;
1547 GdbCommand(false, "-break-insert %s:%d", bp.relativeFilePath, lineNumber);
1550 bp.inserted = (bp.bp && bp.bp.number != 0);
1551 ValidateBreakpoint(bp);
1564 void GdbBreakpointsInsert()
1568 //if(!breakpointsInserted)
1570 //if(!ignoreBreakpoints)
1571 //breakpointsInserted = true;
1572 for(bp : ide.workspace.breakpoints)
1574 if(!bp.inserted && bp.type == user)
1576 if(!ignoreBreakpoints && bp.enabled)
1578 sentBreakInsert = true;
1579 GdbCommand(false, "-break-insert %s:%d", bp.relativeFilePath, bp.line);
1582 bp.inserted = (bp.bp && bp.bp.number != 0);
1584 ValidateBreakpoint(bp);
1590 printf("problem\n");
1592 bp.bp = GdbDataBreakpoint { };
1596 if(bpRunToCursor && !bpRunToCursor.inserted)
1598 sentBreakInsert = true;
1599 GdbCommand(false, "-break-insert %s:%d", bpRunToCursor.relativeFilePath, bpRunToCursor.line);
1600 bpRunToCursor.bp = bpItem;
1602 bpRunToCursor.inserted = (bpRunToCursor.bp && bpRunToCursor.bp.number != 0);
1603 ValidateBreakpoint(bpRunToCursor);
1609 void GdbBreakpointsDelete(bool deleteRunToCursor)
1611 //breakpointsInserted = false;
1614 for(bp : ide.workspace.breakpoints)
1617 GdbCommand(false, "-break-delete %d", bp.bp.number);
1618 bp.inserted = false;
1620 //check here (reply form -break-delete, returns bpitem?)
1623 if(deleteRunToCursor && bpRunToCursor)
1625 GdbCommand(false, "-break-delete %d", bpRunToCursor.bp.number);
1626 bpRunToCursor.inserted = false;
1627 bpRunToCursor.bp = bpItem;
1628 //check here (reply form -break-delete, returns bpitem?)
1637 stackFrames.Free(Frame::Free);
1638 GdbCommand(false, "-stack-info-depth");
1640 GdbCommand(false, "-stack-info-depth 192");
1641 if(frameCount && frameCount <= 192)
1642 GdbCommand(false, "-stack-list-frames 0 191");
1645 GdbCommand(false, "-stack-list-frames 0 95");
1646 GdbCommand(false, "-stack-list-frames %d %d", Max(frameCount - 96, 96), frameCount - 1);
1648 GdbCommand(false, "");
1655 char escaped[MAX_LOCATION];
1656 strescpy(escaped, targetFile);
1657 GdbCommand(false, "file \"%s\"", escaped); //GDB/MI Missing Implementation -symbol-file, -target-attach
1662 for(prj : ide.workspace.projects)
1664 if(prj == ide.workspace.projects.firstIterator.data)
1667 //PrintLn("THIS: ", (String)prj.topNode.path);
1668 GdbCommand(false, "-environment-directory \"%s\"", prj.topNode.path);
1669 //GdbCommand(false, ""); // why this empty GDB command
1672 for(dir : ide.workspace.sourceDirs)
1674 GdbCommand(false, "-environment-directory \"%s\"", dir);
1675 //GdbCommand(false, ""); // why this empty GDB command
1677 GdbInsertInternalBreakpoint();
1683 void GdbTargetRelease()
1687 GdbBreakpointsDelete(true);
1688 GdbCommand(false, "file"); //GDB/MI Missing Implementation -target-detach
1694 void GdbDebugBreak(bool internal)
1699 breakType = DebuggerAction::internal;
1703 //ide.AdjustDebugMenus();
1707 if(Process_Break(targetProcessId)) //GdbCommand(false, "-exec-interrupt");
1708 serialSemaphore.Wait();
1711 ChangeState(loaded);
1712 targetProcessId = 0;
1713 //ide.AdjustDebugMenus();
1718 ide.outputView.debugBox.Logf("Debugger Error: GdbDebugBreak with not target id should never happen\n");
1725 ShowDebuggerViews();
1726 GdbCommand(true, "-exec-run");
1729 void GdbExecContinue(bool focus)
1732 GdbCommand(focus, "-exec-continue");
1738 GdbCommand(true, "-exec-next");
1744 GdbCommand(true, "-exec-step");
1747 void GdbExecFinish()
1750 GdbCommand(true, "-exec-finish");
1753 void GdbExecCommon()
1755 ClearBreakDisplay();
1756 GdbBreakpointsInsert();
1759 #ifdef GDB_DEBUG_GUI
1760 void SendGDBCommand(char * command)
1762 DebuggerState oldState = state;
1767 GdbDebugBreak(true);
1770 GdbCommand(false, command);
1773 if(oldState == running)
1774 GdbExecContinue(false);
1778 void ClearBreakDisplay()
1781 activeFrameLevel = -1;
1792 stackFrames.Free(Frame::Free);
1793 WatchesCodeEditorLinkRelease();
1794 ide.callStackView.Clear();
1795 ide.threadsView.Clear();
1802 GdbCommand(false, "-interpreter-exec console \"kill\""); // should use -exec-abort -- GDB/MI implementation incomplete
1809 char oldDirectory[MAX_LOCATION];
1810 char tempPath[MAX_LOCATION];
1811 char command[MAX_LOCATION];
1812 char oldPath[MAX_LOCATION * 65];
1813 Project project = ide.project;
1814 DirExpression targetDirExp = project.targetDir;
1816 GetEnvironment("PATH", oldPath, sizeof(oldPath));
1818 prjConfig = project.config;
1820 ChangeState(loaded);
1822 sentBreakInsert = false;
1826 //breakpointsInserted = false;
1828 ide.outputView.ShowClearSelectTab(debug);
1829 ide.outputView.debugBox.Logf("Starting debug mode\n");
1831 #ifdef GDB_DEBUG_CONSOLE
1832 Log("Starting GDB"); Log("\n");
1834 #ifdef GDB_DEBUG_OUTPUT
1835 ide.outputView.gdbBox.Logf("run: Starting GDB\n");
1838 strcpy(tempPath, ide.workspace.projectDir);
1839 PathCatSlash(tempPath, targetDirExp.dir);
1841 targetDir = CopyString(tempPath);
1842 project.CatTargetFileName(tempPath);
1844 targetFile = CopyString(tempPath);
1846 GetWorkingDir(oldDirectory, MAX_LOCATION);
1847 if(ide.workspace.debugDir && ide.workspace.debugDir[0])
1849 char temp[MAX_LOCATION];
1850 strcpy(temp, ide.workspace.projectDir);
1851 PathCatSlash(temp, ide.workspace.debugDir);
1852 ChangeWorkingDir(temp);
1855 ChangeWorkingDir(ide.workspace.projectDir);
1859 // TODO: This pollutes the environment, but at least it works
1860 // It shouldn't really affect the IDE as the PATH gets restored and other variables set for testing will unlikely cause problems
1861 // What is the proper solution for this? DualPipeOpenEnv?
1862 // gdb set environment commands don't seem to take effect
1863 for(e : ide.workspace.environmentVars)
1865 SetEnvironment(e.name, e.string);
1868 sprintf(command, "gdb -n -silent --interpreter=mi2"); //-async //\"%s\"
1870 gdbHandle = DualPipeOpen(PipeOpenMode { output = 1, error = 2, input = 1 }, command);
1873 ide.outputView.debugBox.Logf("Debugger Fatal Error: Couldn't start GDB\n");
1881 gdbProcessId = gdbHandle.GetProcessID();
1884 ide.outputView.debugBox.Logf("Debugger Fatal Error: Couldn't get GDB process ID\n");
1890 serialSemaphore.Wait();
1895 //ChangeState(terminated);
1896 //ide.AdjustDebugMenus();
1902 #if defined(__unix__)
1904 CreateTemporaryDir(progFifoDir, "ecereide");
1905 strcpy(progFifoPath, progFifoDir);
1906 PathCat(progFifoPath, "ideprogfifo");
1907 if(!mkfifo(progFifoPath, 0600))
1909 //fileCreated = true;
1914 ide.outputView.debugBox.Logf("err: Unable to create FIFO %s\n", progFifoPath);
1919 progThread.terminate = false;
1920 progThread.Create();
1923 #if defined(__WIN32__)
1924 GdbCommand(false, "-gdb-set new-console on");
1927 GdbCommand(false, "-gdb-set verbose off");
1928 //GdbCommand(false, "-gdb-set exec-done-display on");
1929 GdbCommand(false, "-gdb-set step-mode off");
1930 GdbCommand(false, "-gdb-set unwindonsignal on");
1931 //GdbCommand(false, "-gdb-set shell on");
1932 GdbCommand(false, "set print elements 992");
1933 GdbCommand(false, "-gdb-set backtrace limit 100000");
1935 #if defined(__unix__)
1936 GdbCommand(false, "-inferior-tty-set %s", progFifoPath);
1939 GdbCommand(false, "-gdb-set args %s", ide.workspace.commandLineArgs ? ide.workspace.commandLineArgs : "");
1941 for(e : ide.workspace.environmentVars)
1943 GdbCommand(false, "set environment %s=%s", e.name, e.string);
1950 ChangeWorkingDir(oldDirectory);
1951 SetEnvironment("PATH", oldPath);
1955 delete targetDirExp;
1961 if(gdbHandle && gdbProcessId)
1963 GdbCommand(false, "-gdb-exit");
1978 ChangeState(terminated); // this state change seems to be superfluous, is it safety for something?
1982 for(bp : ide.workspace.breakpoints)
1983 bp.inserted = false;
1985 bp.inserted = false;
1987 bpRunToCursor.inserted = false;
1989 ide.outputView.debugBox.Logf("Debugging stopped\n");
1990 ClearBreakDisplay();
1991 //ide.AdjustDebugMenus();
1994 #if defined(__unix__)
1995 if(FileExists(progFifoPath)) //fileCreated)
1997 progThread.terminate = true;
2000 fifoFile.CloseInput();
2006 DeleteFile(progFifoPath);
2007 progFifoPath[0] = '\0';
2013 void WatchesCodeEditorLinkInit()
2016 char tempPath[MAX_LOCATION];
2017 char path[MAX_LOCATION];
2019 //void MakeFilePathProjectRelative(char * path, char * relativePath)
2020 if(!ide.projectView.GetRelativePath(activeFrame.file, tempPath))
2021 strcpy(tempPath, activeFrame.file);
2023 strcpy(path, ide.workspace.projectDir);
2024 PathCat(path, tempPath);
2025 codeEditor = (CodeEditor)ide.OpenFile(path, Normal, false, null, no);
2028 for(srcDir : ide.workspace.sourceDirs)
2030 strcpy(path, srcDir);
2031 PathCat(path, tempPath);
2032 codeEditor = (CodeEditor)ide.OpenFile(path, Normal, false, null, no);
2033 if(codeEditor) break;
2038 if(activeFrame && !activeFrame.absoluteFile && activeFrame.file)
2039 activeFrame.absoluteFile = ide.workspace.GetAbsolutePathFromRelative(activeFrame.file);
2040 if(!activeFrame || !activeFrame.absoluteFile)
2043 codeEditor = (CodeEditor)ide.OpenFile(activeFrame.absoluteFile, normal, false, null, no, normal);
2046 codeEditor.inUseDebug = true;
2049 //watchesInit = true;
2052 void WatchesCodeEditorLinkRelease()
2058 codeEditor.inUseDebug = false;
2059 if(!codeEditor.visible)
2060 codeEditor.Destroy(0);
2066 bool ResolveWatch(Watch wh)
2068 bool result = false;
2081 char watchmsg[MAX_F_STRING];
2082 if(state == stopped && !codeEditor)
2083 wh.value = CopyString("No source file found for selected frame");
2084 //if(codeEditor && state == stopped || state != stopped)
2087 Module backupPrivateModule;
2088 Context backupContext;
2089 Class backupThisClass;
2093 backupPrivateModule = GetPrivateModule();
2094 backupContext = GetCurrentContext();
2095 backupThisClass = GetThisClass();
2098 SetPrivateModule(codeEditor.privateModule);
2099 SetCurrentContext(codeEditor.globalContext);
2100 SetTopContext(codeEditor.globalContext);
2101 SetGlobalContext(codeEditor.globalContext);
2102 SetGlobalData(&codeEditor.globalData);
2105 exp = ParseExpressionString(wh.expression);
2107 if(exp && !parseError)
2109 if(GetPrivateModule())
2112 DebugFindCtxTree(codeEditor.ast, activeFrame.line, 0);
2113 ProcessExpressionType(exp);
2115 wh.type = exp.expType;
2118 DebugComputeExpression(exp);
2120 /*if(exp.hasAddress)
2122 char temp[MAX_F_STRING];
2123 sprintf(temp, "0x%x", exp.address);
2124 wh.address = CopyString(temp);
2125 // wh.address = CopyStringf("0x%x", exp.address);
2130 Type dataType = exp.expType;
2133 char temp[MAX_F_STRING];
2134 switch(dataType.kind)
2137 sprintf(temp, "%i", exp.val.c);
2140 sprintf(temp, "%i", exp.val.s);
2145 sprintf(temp, "%i", exp.val.i);
2148 sprintf(temp, "%i", exp.val.i64);
2151 sprintf(temp, "%i", exp.val.p);
2156 long v = (long)exp.val.f;
2157 sprintf(temp, "%i", v);
2162 long v = (long)exp.val.d;
2163 sprintf(temp, "%i", v);
2168 wh.intVal = CopyString(temp);
2169 switch(dataType.kind)
2172 sprintf(temp, "0x%x", exp.val.c);
2175 sprintf(temp, "0x%x", exp.val.s);
2179 sprintf(temp, "0x%x", exp.val.i);
2182 sprintf(temp, "0x%x", exp.val.i64);
2185 sprintf(temp, "0x%x", exp.val.i64);
2188 sprintf(temp, "0x%x", exp.val.p);
2193 long v = (long)exp.val.f;
2194 sprintf(temp, "0x%x", v);
2199 long v = (long)exp.val.d;
2200 sprintf(temp, "0x%x", v);
2205 wh.hexVal = CopyString(temp);
2206 switch(dataType.kind)
2209 sprintf(temp, "0o%o", exp.val.c);
2212 sprintf(temp, "0o%o", exp.val.s);
2216 sprintf(temp, "0o%o", exp.val.i);
2219 sprintf(temp, "0o%o", exp.val.i64);
2222 sprintf(temp, "0o%o", exp.val.i64);
2225 sprintf(temp, "0o%o", exp.val.p);
2230 long v = (long)exp.val.f;
2231 sprintf(temp, "0o%o", v);
2236 long v = (long)exp.val.d;
2237 sprintf(temp, "0o%o", v);
2242 wh.octVal = CopyString(temp);
2245 // WHATS THIS HERE ?
2246 if(exp.type == constantExp && exp.constant)
2247 wh.constant = CopyString(exp.constant);
2253 case symbolErrorExp:
2254 sprintf(watchmsg, "Symbol \"%s\" not found", exp.identifier.string);
2256 case structMemberSymbolErrorExp:
2257 // todo get info as in next case (ExpClassMemberSymbolError)
2258 sprintf(watchmsg, "Error: Struct member not found for \"%s\"", wh.expression);
2260 case classMemberSymbolErrorExp:
2263 Expression memberExp = exp.member.exp;
2264 Identifier memberID = exp.member.member;
2265 Type type = memberExp.expType;
2268 _class = (memberID && memberID.classSym) ? memberID.classSym.registered : ((type.kind == classType && type._class) ? type._class.registered : null);
2271 char string[256] = "";
2273 PrintType(type, string, false, true);
2274 classSym = FindClass(string);
2275 _class = classSym ? classSym.registered : null;
2278 sprintf(watchmsg, "Member \"%s\" not found in class \"%s\"", memberID ? memberID.string : "", _class.name);
2280 sprintf(watchmsg, "Member \"%s\" not found in unregistered class? (Should never get this message)", memberID ? memberID.string : "");
2283 sprintf(watchmsg, "Member \"%s\" not found in no type? (Should never get this message)", memberID ? memberID.string : "");
2286 case memoryErrorExp:
2287 // Need to ensure when set to memoryErrorExp, constant is set
2288 sprintf(watchmsg, "Memory can't be read at %s", /*(exp.type == constantExp) ? */exp.constant /*: null*/);
2290 case dereferenceErrorExp:
2291 sprintf(watchmsg, "Dereference failure for \"%s\"", wh.expression);
2293 case unknownErrorExp:
2294 sprintf(watchmsg, "Unknown error for \"%s\"", wh.expression);
2296 case noDebuggerErrorExp:
2297 sprintf(watchmsg, "Debugger required for symbol evaluation in \"%s\"", wh.expression);
2299 case debugStateErrorExp:
2300 sprintf(watchmsg, "Incorrect debugger state for symbol evaluation in \"%s\"", wh.expression);
2303 sprintf(watchmsg, "Null type for \"%s\"", wh.expression);
2307 // Temporary Code for displaying Strings
2308 if((exp.expType && ((exp.expType.kind == pointerType ||
2309 exp.expType.kind == arrayType) && exp.expType.type.kind == charType)) ||
2310 (wh.type && wh.type.kind == classType && wh.type._class &&
2311 wh.type._class.registered && wh.type._class.registered.type == normalClass &&
2312 !strcmp(wh.type._class.registered.name, "String")))
2315 if(exp.expType.kind != arrayType || exp.hasAddress)
2321 //char temp[MAX_F_STRING * 32];
2323 ExpressionType evalError = dummyExp;
2324 /*if(exp.expType.kind == arrayType)
2325 sprintf(temp, "(char*)0x%x", exp.address);
2327 sprintf(temp, "(char*)%s", exp.constant);*/
2329 //evaluation = Debugger::EvaluateExpression(temp, &evalError);
2330 address = strtoul(exp.constant, null, 0);
2331 //printf("%x\n", address);
2332 sprintf(value, "0x%08x ", address);
2335 strcat(value, "Null string");
2339 len = strlen(value);
2341 while(!string && size > 2)
2343 string = GdbReadMemory(address, size);
2346 if(string && string[0])
2349 if(UTF8Validate(string))
2354 for(c = 0; (ch = string[c]) && c<4096; c++)
2357 value[len++] = '\0';
2362 ISO8859_1toUTF8(string, value + len, 4096 - len - 30);
2363 strcat(value, ") (ISO8859-1)");
2370 strcat(value, "Empty string");
2374 strcat(value, "Couldn't read memory");
2376 wh.value = CopyString(value);
2379 else if(wh.type && wh.type.kind == classType && wh.type._class &&
2380 wh.type._class.registered && wh.type._class.registered.type == enumClass)
2382 uint64 value = strtoul(exp.constant, null, 0);
2383 Class enumClass = eSystem_FindClass(GetPrivateModule(), wh.type._class.registered.name);
2384 EnumClassData enumeration = (EnumClassData)enumClass.data;
2386 for(item = enumeration.values.first; item; item = item.next)
2387 if((int)item.data == value)
2390 wh.value = CopyString(item.name);
2392 wh.value = CopyString("Invalid Enum Value");
2393 result = (bool)atoi(exp.constant);
2395 else if(wh.type && (wh.type.kind == charType || (wh.type.kind == classType && wh.type._class &&
2396 wh.type._class.registered && !strcmp(wh.type._class.registered.fullName, "ecere::com::unichar"))) )
2403 if(exp.constant[0] == '\'')
2405 if((int)((byte *)exp.constant)[1] > 127)
2408 value = UTF8GetChar(exp.constant + 1, &nb);
2409 if(nb < 2) value = exp.constant[1];
2410 signedValue = value;
2414 signedValue = exp.constant[1];
2416 // Precomp Syntax error with boot strap here:
2417 byte b = (byte)(char)signedValue;
2418 value = (unichar) b;
2424 if(wh.type.kind == charType && wh.type.isSigned)
2426 signedValue = (int)(char)strtol(exp.constant, null, 0);
2428 // Precomp Syntax error with boot strap here:
2429 byte b = (byte)(char)signedValue;
2430 value = (unichar) b;
2435 value = strtoul(exp.constant, null, 0);
2436 signedValue = (int)value;
2440 UTF32toUTF8Len(&value, 1, charString, 5);
2442 sprintf(string, "\'\\0' (0)");
2443 else if(value == '\t')
2444 sprintf(string, "\'\\t' (%d)", value);
2445 else if(value == '\n')
2446 sprintf(string, "\'\\n' (%d)", value);
2447 else if(value == '\r')
2448 sprintf(string, "\'\\r' (%d)", value);
2449 else if(wh.type.kind == charType && wh.type.isSigned)
2450 sprintf(string, "\'%s\' (%d)", charString, signedValue);
2451 else if(value > 256 || wh.type.kind != charType)
2453 if(value > 0x10FFFF || !GetCharCategory(value))
2454 sprintf(string, "Invalid Unicode Keypoint (0x%08X)", value);
2456 sprintf(string, "\'%s\' (U+%04X)", charString, value);
2459 sprintf(string, "\'%s\' (%d)", charString, value);
2461 wh.value = CopyString(string);
2466 wh.value = CopyString(exp.constant);
2467 result = (bool)atoi(exp.constant);
2473 wh.value = PrintHexUInt(exp.address);
2474 result = (bool)exp.address;
2478 char tempString[256];
2479 if(exp.member.memberType == propertyMember)
2480 sprintf(watchmsg, "Missing property evaluation support for \"%s\"", wh.expression);
2482 sprintf(watchmsg, "Evaluation failed for \"%s\" of type \"%s\"", wh.expression,
2483 exp.type.OnGetString(tempString, null, null));
2489 sprintf(watchmsg, "Invalid expression: \"%s\"", wh.expression);
2490 if(exp) FreeExpression(exp);
2493 SetPrivateModule(backupPrivateModule);
2494 SetCurrentContext(backupContext);
2495 SetTopContext(backupContext);
2496 SetGlobalContext(backupContext);
2497 SetThisClass(backupThisClass);
2500 // wh.value = CopyString("No source file found for selected frame");
2503 wh.value = CopyString(watchmsg);
2505 ide.watchesView.UpdateWatch(wh);
2509 void EvaluateWatches()
2511 for(wh : ide.workspace.watches)
2515 char * ::GdbEvaluateExpression(char * expression)
2519 GdbCommand(false, "-data-evaluate-expression \"%s\"", expression);
2521 ide.outputView.debugBox.Logf("Debugger Error: GdbEvaluateExpression\n");
2525 // to be removed... use GdbReadMemory that returns a byte array instead
2526 char * ::GdbReadMemoryString(uint address, int size, char format, int rows, int cols)
2532 printf("GdbReadMemoryString called with size = 0!\n");
2534 GdbCommand(false, "-data-read-memory 0x%08x %c, %d, %d, %d", address, format, size, rows, cols);
2536 ide.outputView.debugBox.Logf("Debugger Error: GdbReadMemoryString\n");
2540 byte * ::GdbReadMemory(uint address, int bytes)
2544 GdbCommand(false, "-data-read-memory 0x%08x %c, 1, 1, %d", address, 'u', bytes);
2547 printf("GdbReadMemory called with bytes = 0!\n");
2550 ide.outputView.debugBox.Logf("Debugger Error: GdbReadMemory\n");
2551 else if(eval.result && strcmp(eval.result, "N/A"))
2553 byte * result = new byte[bytes];
2554 byte * string = eval.result;
2558 result[c++] = (byte)strtol(string, &string, 10);
2574 void EventHit(GdbDataStop stopItem)
2576 bool conditionMet = true;
2577 Breakpoint bp = bpHit;
2579 if(!bp && bpRunToCursor)
2583 GdbCommand(false, "-break-delete %d", bp.bp.number);
2588 if(bp.type == user && bp.line != stopItem.frame.line)
2590 bp.line = stopItem.frame.line;
2591 ide.breakpointsView.UpdateBreakpoint(bp.row);
2592 ide.workspace.Save();
2598 case internalWinMain:
2599 GdbBreakpointsInsert();
2600 if(userBreakOnInternBreak)
2602 userBreakOnInternBreak = false;
2603 // Why was SelectFrame missing here?
2604 SelectFrame(activeFrameLevel);
2605 GoToStackFrameLine(activeFrameLevel, true);
2606 //ide.AdjustDebugMenus();
2611 GdbExecContinue(false);
2613 case internalModulesLoaded:
2615 GdbBreakpointsInsert();
2616 GdbExecContinue(false);
2621 conditionMet = ResolveWatch(bp.condition);
2622 if(conditionMet && (bp.level == -1 || bp.level == frameCount))
2625 if(bp.hits > bp.ignore)
2627 ignoreBreakpoints = false;
2628 // Why was SelectFrame missing here?
2629 SelectFrame(activeFrameLevel);
2630 GoToStackFrameLine(activeFrameLevel, true);
2631 //ide.AdjustDebugMenus();
2634 if(bp.type == BreakpointType::runToCursor)
2636 delete bpRunToCursor;
2637 bpRunToCursor = null;
2643 ide.breakpointsView.UpdateBreakpoint(bp.row);*/
2644 GdbExecContinue(false);
2648 GdbExecContinue(false);
2653 ide.outputView.debugBox.Logf("Debugger Error: Breakpoint hit could not match breakpoint instance\n");
2656 void GdbThreadExit()
2658 if(state != terminated)
2660 ChangeState(terminated);
2661 targetProcessId = 0;
2662 ClearBreakDisplay();
2663 //ide.AdjustDebugMenus();
2667 serialSemaphore.Release();
2672 ide.outputView.debugBox.Logf("Debugger Fatal Error: GDB lost\n");
2673 ide.outputView.debugBox.Logf("Debugging stopped\n");
2676 //ChangeState(terminated);
2680 void GdbThreadMain(char * output)
2683 Array<char *> outTokens { minAllocSize = 50 };
2684 Array<char *> subTokens { minAllocSize = 50 };
2685 DebugListItem item { };
2686 DebugListItem item2 { };
2687 bool setWaitingForPID = false;
2689 #if defined(GDB_DEBUG_CONSOLE) || defined(GDB_DEBUG_GUI)
2690 #ifdef GDB_DEBUG_CONSOLE
2691 Log(output); Log("\n");
2693 #ifdef GDB_DEBUG_OUTPUT
2695 int len = strlen(output);
2703 for(c = 0; c < len / 1024; c++)
2705 strncpy(tmp, start, 1024);
2706 ide.outputView.gdbBox.Logf("out: %s\n", tmp);
2709 ide.outputView.gdbBox.Logf("out: %s\n", start);
2713 ide.outputView.gdbBox.Logf("out: %s\n", output);
2717 #ifdef GDB_DEBUG_CONSOLE
2718 strcpy(lastGdbOutput, output);
2720 #ifdef GDB_DEBUG_GUI
2721 if(ide.gdbDialog) ide.gdbDialog.AddOutput(output);
2728 if(strstr(output, "No debugging symbols found") || strstr(output, "(no debugging symbols found)"))
2731 ide.outputView.debugBox.Logf("Target doesn't contain debug information!\n");
2737 if(TokenizeList(output, ',', outTokens) && !strcmp(outTokens[0], "^done"))
2739 //if(outTokens.count == 1)
2744 ChangeState(loaded);
2745 targetProcessId = 0;
2746 if(outTokens.count > 1 && TokenizeListItem(outTokens[1], item))
2748 if(!strcmp(item.name, "reason"))
2750 char * reason = item.value;
2751 StripQuotes(reason, reason);
2752 if(!strcmp(reason, "exited-normally") || !strcmp(reason, "exited") || !strcmp(reason, "exited-signalled"))
2755 if(outTokens.count > 2 && TokenizeListItem(outTokens[2], item2))
2757 StripQuotes(item2.value, item2.value);
2758 if(!strcmp(item2.name, "exit-code"))
2759 exitCode = item2.value;
2765 HandleExit(reason, exitCode);
2769 DebuggerProtocolUnknown("Unknown kill reply", item.name);
2772 HandleExit(null, null);
2775 if(outTokens.count > 1 && TokenizeListItem(outTokens[1], item))
2777 if(!strcmp(item.name, "bkpt"))
2779 sentBreakInsert = false;
2782 printf("problem\n");
2784 bpItem = GdbDataBreakpoint { };
2785 item.value = StripCurlies(item.value);
2786 TokenizeList(item.value, ',', subTokens);
2787 for(i = 0; i < subTokens.count; i++)
2789 if(TokenizeListItem(subTokens[i], item))
2791 StripQuotes(item.value, item.value);
2792 if(!strcmp(item.name, "number"))
2793 bpItem.number = atoi(item.value);
2794 else if(!strcmp(item.name, "type"))
2795 bpItem.type = CopyString(item.value);
2796 else if(!strcmp(item.name, "disp"))
2797 bpItem.disp = CopyString(item.value);
2798 else if(!strcmp(item.name, "enabled"))
2799 bpItem.enabled = (!strcmpi(item.value, "y"));
2800 else if(!strcmp(item.name, "addr"))
2801 bpItem.addr = CopyString(item.value);
2802 else if(!strcmp(item.name, "func"))
2803 bpItem.func = CopyString(item.value);
2804 else if(!strcmp(item.name, "file"))
2805 bpItem.file = item.value;
2806 else if(!strcmp(item.name, "line"))
2807 bpItem.line = atoi(item.value);
2808 else if(!strcmp(item.name, "at"))
2809 bpItem.at = CopyString(item.value);
2810 else if(!strcmp(item.name, "times"))
2811 bpItem.times = atoi(item.value);
2814 //breakType = bpValidation;
2815 //app.SignalEvent();
2816 subTokens.RemoveAll();
2818 else if(!strcmp(item.name, "BreakpointTable"))
2819 ide.outputView.debugBox.Logf("Debugger Error: Command reply BreakpointTable not handled\n");
2820 else if(!strcmp(item.name, "depth"))
2822 StripQuotes(item.value, item.value);
2823 frameCount = atoi(item.value);
2825 stackFrames.Free(Frame::Free);
2827 else if(!strcmp(item.name, "stack"))
2830 if(stackFrames.count)
2831 ide.callStackView.Logf("...\n");
2834 item.value = StripBrackets(item.value);
2835 TokenizeList(item.value, ',', subTokens);
2836 for(i = 0; i < subTokens.count; i++)
2838 if(TokenizeListItem(subTokens[i], item))
2840 if(!strcmp(item.name, "frame"))
2843 stackFrames.Add(frame);
2844 item.value = StripCurlies(item.value);
2845 ParseFrame(frame, item.value);
2846 if(frame.file && frame.from)
2847 DebuggerProtocolUnknown("Unexpected frame file and from members present", "");
2851 if(activeFrameLevel == -1)
2853 if(ide.projectView.IsModuleInProject(frame.file));
2855 if(frame.level != 0)
2857 //stopItem.frame = frame;
2858 breakType = selectFrame;
2861 activeFrame = frame;
2862 activeFrameLevel = frame.level;
2865 ide.callStackView.Logf("%3d ", frame.level);
2866 if(!strncmp(frame.func, "__ecereMethod_", strlen("__ecereMethod_")))
2867 ide.callStackView.Logf("%s Method, %s:%d\n", &frame.func[strlen("__ecereMethod_")], (s = CopySystemPath(frame.file)), frame.line);
2868 else if(!strncmp(frame.func, "__ecereProp_", strlen("__ecereProp_")))
2869 ide.callStackView.Logf("%s Property, %s:%d\n", &frame.func[strlen("__ecereProp_")], (s = CopySystemPath(frame.file)), frame.line);
2870 else if(!strncmp(frame.func, "__ecereConstructor_", strlen("__ecereConstructor_")))
2871 ide.callStackView.Logf("%s Constructor, %s:%d\n", &frame.func[strlen("__ecereConstructor_")], (s = CopySystemPath(frame.file)), frame.line);
2872 else if(!strncmp(frame.func, "__ecereDestructor_", strlen("__ecereDestructor_")))
2873 ide.callStackView.Logf("%s Destructor, %s:%d\n", &frame.func[strlen("__ecereDestructor_")], (s = CopySystemPath(frame.file)), frame.line);
2875 ide.callStackView.Logf("%s Function, %s:%d\n", frame.func, (s = CopySystemPath(frame.file)), frame.line);
2880 ide.callStackView.Logf("%3d ", frame.level);
2885 ide.callStackView.Logf("inside %s, %s\n", frame.func, (s = CopySystemPath(frame.from)));
2889 ide.callStackView.Logf("%s\n", frame.func);
2891 ide.callStackView.Logf("unknown source\n");
2895 DebuggerProtocolUnknown("Unknown stack content", item.name);
2898 if(activeFrameLevel == -1)
2900 activeFrameLevel = 0;
2901 activeFrame = stackFrames.first;
2903 ide.callStackView.Home();
2905 subTokens.RemoveAll();
2907 /*else if(!strcmp(item.name, "frame"))
2910 item.value = StripCurlies(item.value);
2911 ParseFrame(&frame, item.value);
2913 else if(!strcmp(item.name, "thread-ids"))
2915 ide.threadsView.Clear();
2916 item.value = StripCurlies(item.value);
2917 TokenizeList(item.value, ',', subTokens);
2918 for(i = subTokens.count - 1; ; i--)
2920 if(TokenizeListItem(subTokens[i], item))
2922 if(!strcmp(item.name, "thread-id"))
2925 StripQuotes(item.value, item.value);
2926 value = atoi(item.value);
2927 ide.threadsView.Logf("%3d \n", value);
2930 DebuggerProtocolUnknown("Unknown threads content", item.name);
2935 ide.threadsView.Home();
2937 subTokens.RemoveAll();
2938 //if(!strcmp(outTokens[2], "number-of-threads"))
2940 else if(!strcmp(item.name, "new-thread-id"))
2942 StripQuotes(item.value, item.value);
2943 activeThread = atoi(item.value);
2945 else if(!strcmp(item.name, "value"))
2947 StripQuotes(item.value, item.value);
2948 eval.result = CopyString(item.value);
2949 eval.active = false;
2951 else if(!strcmp(item.name, "addr"))
2953 for(i = 2; i < outTokens.count; i++)
2955 if(TokenizeListItem(outTokens[i], item))
2957 if(!strcmp(item.name, "total-bytes"))
2959 StripQuotes(item.value, item.value);
2960 eval.bytes = atoi(item.value);
2962 else if(!strcmp(item.name, "next-row"))
2964 StripQuotes(item.value, item.value);
2965 eval.nextBlockAddress = strtoul(item.value, null, 0);
2967 else if(!strcmp(item.name, "memory"))
2971 //StripQuotes(item.value, item.value);
2972 item.value = StripBrackets(item.value);
2973 // this should be treated as a list...
2974 item.value = StripCurlies(item.value);
2975 TokenizeList(item.value, ',', subTokens);
2976 for(j = 0; j < subTokens.count; j++)
2978 if(TokenizeListItem(subTokens[j], item))
2980 if(!strcmp(item.name, "data"))
2982 item.value = StripBrackets(item.value);
2983 StripQuotes2(item.value, item.value);
2984 eval.result = CopyString(item.value);
2985 eval.active = false;
2989 subTokens.RemoveAll();
2994 else if(!strcmp(item.name, "source-path"))
2998 DebuggerProtocolUnknown("Unknown command reply", item.name);
3001 else if(!strcmp(outTokens[0], "^running"))
3003 waitingForPID = true;
3004 setWaitingForPID = true;
3006 else if(!strcmp(outTokens[0], "^exit"))
3008 ChangeState(terminated);
3009 //ide.AdjustDebugMenus();
3010 // ide.outputView.debugBox.Logf("Exit\n");
3013 serialSemaphore.Release();
3015 else if(!strcmp(outTokens[0], "^error"))
3019 sentBreakInsert = false;
3022 printf("problem\n");
3024 bpItem = GdbDataBreakpoint { };
3027 if(outTokens.count > 1 && TokenizeListItem(outTokens[1], item))
3029 if(!strcmp(item.name, "msg"))
3031 StripQuotes(item.value, item.value);
3034 eval.active = false;
3036 if(strstr(item.value, "No symbol") && strstr(item.value, "in current context"))
3037 eval.error = symbolNotFound;
3038 else if(strstr(item.value, "Cannot access memory at address"))
3039 eval.error = memoryCantBeRead;
3041 eval.error = unknown;
3043 else if(!strcmp(item.value, "Previous frame inner to this frame (corrupt stack?)"))
3046 else if(!strncmp(item.value, "Cannot access memory at address", 31))
3049 else if(!strcmp(item.value, "Cannot find bounds of current function"))
3051 ChangeState(stopped);
3052 gdbHandle.Printf("-exec-continue\n");
3054 else if(!strcmp(item.value, "ptrace: No such process."))
3056 ChangeState(loaded);
3057 targetProcessId = 0;
3058 //ide.AdjustDebugMenus();
3060 else if(!strcmp(item.value, "Function \\\"WinMain\\\" not defined."))
3063 else if(!strcmp(item.value, "You can't do that without a process to debug."))
3065 ChangeState(loaded);
3066 targetProcessId = 0;
3067 //ide.AdjustDebugMenus();
3069 else if(strstr(item.value, "No such file or directory."))
3071 ChangeState(loaded);
3072 targetProcessId = 0;
3073 //ide.AdjustDebugMenus();
3078 if(strlen(item.value) < MAX_F_STRING)
3081 ide.outputView.debugBox.Logf("GDB: %s\n", (s = CopyUnescapedString(item.value)));
3085 ide.outputView.debugBox.Logf("GDB: %s\n", item.value);
3091 DebuggerProtocolUnknown("Unknown error content", item.name);
3094 DebuggerProtocolUnknown("Unknown result-record", outTokens[0]);
3096 outTokens.RemoveAll();
3099 DebuggerProtocolUnknown("Unknown status-async-output", outTokens[0]);
3102 if(TokenizeList(output, ',', outTokens) && !strcmp(outTokens[0], "=thread-group-created")) //=thread-group-created,id="7611"
3104 else if(!strcmp(outTokens[0], "=thread-created")) //=thread-created,id="1",group-id="7611"
3106 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"
3109 DebuggerProtocolUnknown("Unknown notify-async-output", outTokens[0]);
3110 outTokens.RemoveAll();
3114 if(TokenizeList(output, ',', outTokens))
3116 if(!strcmp(outTokens[0],"*running"))
3118 waitingForPID = true;
3119 setWaitingForPID = true;
3121 else if(!strcmp(outTokens[0], "*stopped"))
3123 ChangeState(stopped);
3125 if(outTokens.count > 1 && TokenizeListItem(outTokens[1], item))
3127 if(!strcmp(item.name, "reason"))
3129 char * reason = item.value;
3130 StripQuotes(reason, reason);
3131 if(!strcmp(reason, "exited-normally") || !strcmp(reason, "exited") || !strcmp(reason, "exited-signalled"))
3134 if(outTokens.count > 2 && TokenizeListItem(outTokens[2], item2))
3136 StripQuotes(item2.value, item2.value);
3137 if(!strcmp(item2.name, "exit-code"))
3138 exitCode = item2.value;
3144 HandleExit(reason, exitCode);
3146 else if(!strcmp(reason, "breakpoint-hit"))
3150 printf("problem\n");
3152 stopItem = GdbDataStop { };
3154 for(i = 2; i < outTokens.count; i++)
3156 TokenizeListItem(outTokens[i], item);
3157 StripQuotes(item.value, item.value);
3158 if(!strcmp(item.name, "bkptno"))
3159 stopItem.bkptno = atoi(item.value);
3160 else if(!strcmp(item.name, "thread-id"))
3161 stopItem.threadid = atoi(item.value);
3162 else if(!strcmp(item.name, "frame"))
3164 item.value = StripCurlies(item.value);
3165 ParseFrame(stopItem.frame, item.value);
3168 DebuggerProtocolUnknown("Unknown breakpoint hit item name", item.name);
3173 else if(!strcmp(reason, "end-stepping-range"))
3177 printf("problem\n");
3179 stopItem = GdbDataStop { };
3181 for(i = 2; i < outTokens.count; i++)
3183 TokenizeListItem(outTokens[i], item);
3184 StripQuotes(item.value, item.value);
3185 if(!strcmp(item.name, "thread-id"))
3186 stopItem.threadid = atoi(item.value);
3187 else if(!strcmp(item.name, "frame"))
3189 item.value = StripCurlies(item.value);
3190 ParseFrame(stopItem.frame, item.value);
3192 else if(!strcmp(item.name, "reason"))
3194 else if(!strcmp(item.name, "bkptno"))
3197 DebuggerProtocolUnknown("Unknown end of stepping range item name", item.name);
3201 //ide.AdjustDebugMenus();
3204 else if(!strcmp(reason, "function-finished"))
3208 printf("problem\n");
3210 stopItem = GdbDataStop { };
3211 stopItem.reason = CopyString(reason);
3213 for(i = 2; i < outTokens.count; i++)
3215 TokenizeListItem(outTokens[i], item);
3216 StripQuotes(item.value, item.value);
3217 if(!strcmp(item.name, "thread-id"))
3218 stopItem.threadid = atoi(item.value);
3219 else if(!strcmp(item.name, "frame"))
3221 item.value = StripCurlies(item.value);
3222 ParseFrame(stopItem.frame, item.value);
3224 else if(!strcmp(item.name, "gdb-result-var"))
3225 stopItem.gdbResultVar = CopyString(item.value);
3226 else if(!strcmp(item.name, "return-value"))
3227 stopItem.returnValue = CopyString(item.value);
3229 DebuggerProtocolUnknown("Unknown function finished item name", item.name);
3232 event = functionEnd;
3233 //ide.AdjustDebugMenus();
3236 else if(!strcmp(reason, "signal-received"))
3240 printf("problem\n");
3242 stopItem = GdbDataStop { };
3243 stopItem.reason = CopyString(reason);
3245 for(i = 2; i < outTokens.count; i++)
3247 TokenizeListItem(outTokens[i], item);
3248 StripQuotes(item.value, item.value);
3249 if(!strcmp(item.name, "signal-name"))
3250 stopItem.name = CopyString(item.value);
3251 else if(!strcmp(item.name, "signal-meaning"))
3252 stopItem.meaning = CopyString(item.value);
3253 else if(!strcmp(item.name, "thread-id"))
3254 stopItem.threadid = atoi(item.value);
3255 else if(!strcmp(item.name, "frame"))
3257 item.value = StripCurlies(item.value);
3258 ParseFrame(stopItem.frame, item.value);
3261 DebuggerProtocolUnknown("Unknown signal reveived item name", item.name);
3263 if(!strcmp(stopItem.name, "SIGTRAP"))
3275 //ide.AdjustDebugMenus(); ide.Update(null);
3281 //ide.AdjustDebugMenus(); ide.Update(null);
3284 else if(!strcmp(reason, "watchpoint-trigger"))
3285 DebuggerProtocolUnknown("Reason watchpoint trigger not handled", "");
3286 else if(!strcmp(reason, "read-watchpoint-trigger"))
3287 DebuggerProtocolUnknown("Reason read watchpoint trigger not handled", "");
3288 else if(!strcmp(reason, "access-watchpoint-trigger"))
3289 DebuggerProtocolUnknown("Reason access watchpoint trigger not handled", "");
3290 else if(!strcmp(reason, "watchpoint-scope"))
3291 DebuggerProtocolUnknown("Reason watchpoint scope not handled", "");
3292 else if(!strcmp(reason, "location-reached"))
3293 DebuggerProtocolUnknown("Reason location reached not handled", "");
3295 DebuggerProtocolUnknown("Unknown reason", reason);
3302 DebuggerProtocolUnknown("Unknown exec-async-output", outTokens[0]);
3303 outTokens.RemoveAll();
3306 if(!strcmpi(output, "(gdb) "))
3310 char exeFile[MAX_LOCATION];
3311 int oldProcessID = targetProcessId;
3312 GetLastDirectory(targetFile, exeFile);
3316 targetProcessId = Process_GetChildExeProcessId(gdbProcessId, exeFile);
3317 if(targetProcessId || gdbHandle.Peek()) break;
3323 ChangeState(running);
3324 //ide.AdjustDebugMenus(); ide.Update(null);
3326 else if(!oldProcessID)
3328 ide.outputView.debugBox.Logf("Debugger Error: No target process ID\n");
3329 // TO VERIFY: The rest of this block has not been thoroughly tested in this particular location
3330 gdbHandle.Printf("-gdb-exit\n");
3332 ChangeState(terminated); //loaded;
3337 for(bp : ide.workspace.breakpoints)
3338 bp.inserted = false;
3341 bp.inserted = false;
3343 bpRunToCursor.inserted = false;
3345 ide.outputView.debugBox.Logf("Debugging stopped\n");
3346 ClearBreakDisplay();
3347 //ide.AdjustDebugMenus(); ide.Update(null);
3349 #if defined(__unix__)
3350 if(FileExists(progFifoPath)) //fileCreated)
3352 progThread.terminate = true;
3355 fifoFile.CloseInput();
3362 DeleteFile(progFifoPath);
3363 progFifoPath[0] = '\0';
3370 serialSemaphore.Release();
3373 DebuggerProtocolUnknown("Unknown prompt", output);
3377 if(!strncmp(output, "&\"warning:", 10))
3380 content = strstr(output, "\"");
3381 StripQuotes(content, content);
3382 content = strstr(content, ":");
3388 ide.outputView.debugBox.LogRaw((s = CopyUnescapedString(content)));
3395 DebuggerProtocolUnknown("Unknown output", output);
3397 if(!setWaitingForPID)
3398 waitingForPID = false;
3399 setWaitingForPID = false;
3407 void RunToCursorPrepare(char * absoluteFilePath, char * relativeFilePath, int lineNumber)
3411 //bpRunToCursor.Free();
3412 bpRunToCursor = Breakpoint { };
3415 bpRunToCursor = Breakpoint { };
3417 if(absoluteFilePath)
3418 bpRunToCursor.absoluteFilePath = CopyString(absoluteFilePath);
3419 if(relativeFilePath)
3420 bpRunToCursor.relativeFilePath = CopyString(relativeFilePath);
3421 bpRunToCursor.line = lineNumber;
3422 bpRunToCursor.type = runToCursor;
3423 bpRunToCursor.enabled = true;
3424 bpRunToCursor.condition = null;
3425 bpRunToCursor.ignore = 0;
3426 bpRunToCursor.level = -1;
3429 ExpressionType ::DebugEvalExpTypeError(char * result)
3435 case symbolNotFound:
3436 return symbolErrorExp;
3437 case memoryCantBeRead:
3438 return memoryErrorExp;
3440 return unknownErrorExp;
3443 char * ::EvaluateExpression(char * expression, ExpressionType * error)
3446 if(ide.projectView && ide.debugger.state == stopped)
3448 result = GdbEvaluateExpression(expression);
3449 *error = DebugEvalExpTypeError(result);
3454 *error = noDebuggerErrorExp;
3459 char * ::ReadMemory(uint address, int size, char format, ExpressionType * error)
3462 char * result = GdbReadMemoryString(address, size, format, 1, 1);
3463 if(!result || !strcmp(result, "N/A"))
3464 *error = memoryErrorExp;
3466 *error = DebugEvalExpTypeError(result);
3471 class GdbThread : Thread
3477 static char output[4096];
3478 Array<char> dynamicBuffer { minAllocSize = 4096 };
3479 DualPipe oldGdbHandle = gdbHandle;
3480 incref oldGdbHandle;
3483 while(debugger.state != terminated && gdbHandle && !gdbHandle.Eof())
3487 result = gdbHandle.Read(output, 1, sizeof(output));
3488 if(debugger.state == terminated || !gdbHandle || gdbHandle.Eof())
3496 for(c = 0; c<result; c++)
3498 if(output[c] == '\n')
3500 int pos = dynamicBuffer.size;
3501 dynamicBuffer.size += c - start;
3502 memcpy(&dynamicBuffer[pos], output + start, c - start);
3503 if(dynamicBuffer.count && dynamicBuffer[dynamicBuffer.count - 1] != '\r')
3504 // COMMENTED OUT DUE TO ISSUE #135, FIXED
3505 //if(dynamicBuffer.array[dynamicBuffer.count - 1] != '\r')
3506 dynamicBuffer.size++;
3507 dynamicBuffer[dynamicBuffer.count - 1] = '\0';
3509 // printf("%s\n", dynamicBuffer.array);
3511 debugger.GdbThreadMain(&dynamicBuffer[0]);
3512 dynamicBuffer.size = 0;
3518 int pos = dynamicBuffer.size;
3519 dynamicBuffer.size += c - start;
3520 memcpy(&dynamicBuffer[pos], output + start, c - start);
3526 printf("Got end of file from GDB!\n");
3530 delete dynamicBuffer;
3531 //if(oldGdbHandle == gdbHandle)
3532 debugger.GdbThreadExit();
3533 delete oldGdbHandle;
3539 #if defined(__unix__)
3544 #include <sys/types.h>
3549 class ProgramThread : Thread
3555 bool fileCreated = false;
3557 static char output[1000];
3560 /*if(!mkfifo(progFifoPath, mask))
3567 ide.outputView.debugBox.Logf("err: Unable to create FIFO %s\n", progFifoPath);
3571 if(FileExists(progFifoPath)) //fileCreated)
3573 fifoFile = FileOpen(progFifoPath, read);
3577 ide.outputView.debugBox.Logf("err: Unable to open FIFO %s for read\n", progFifoPath);
3586 fd = fileno(fifoFile.input);
3588 //fcntl(fd, F_SETFL, fcntl(fd, F_GETFL) | O_NONBLOCK);
3592 while(!terminate && fifoFile && !fifoFile.Eof())
3595 struct timeval time;
3603 selectResult = select(fd + 1, &rs, null, null, &time);
3604 if(FD_ISSET(fd, &rs))
3606 int result = read(fd, output, sizeof(output)-1);
3607 if(!result || (result < 0 && errno != EAGAIN))
3611 output[result] = '\0';
3612 if(strcmp(output,"&\"warning: GDB: Failed to set controlling terminal: Invalid argument\\n\"\n"))
3615 ide.outputView.debugBox.Log(output);
3624 //fifoFile.CloseInput();
3627 ide.outputView.debugBox.Log("\n");
3631 if(FileExists(progFifoPath)) //fileCreated)
3633 DeleteFile(progFifoPath);
3634 progFifoPath[0] = '\0';
3642 class Argument : struct
3644 Argument prev, next;
3660 class Frame : struct
3669 property char * from { set { delete from; if(value) from = CopyUnescapedUnixPath(value); } }
3671 property char * file { set { delete file; if(value) file = CopyUnescapedUnixPath(value); } }
3672 char * absoluteFile;
3681 delete absoluteFile;
3682 args.Free(Argument::Free);
3691 class GdbDataStop : struct
3708 char * gdbResultVar;
3718 if(!strcmp(reason, "signal-received"))
3723 else if(!strcmp(reason, "function-finished"))
3725 delete gdbResultVar;
3730 if(frame) frame.Free();
3739 class GdbDataBreakpoint : struct
3748 property char * file { set { delete file; if(value) file = CopyUnescapedUnixPath(value); } }
3763 ~GdbDataBreakpoint()
3769 class Breakpoint : struct
3773 char * relativeFilePath;
3774 char * absoluteFilePath;
3782 BreakpointType type;
3785 GdbDataBreakpoint bp;
3787 char * LocationToString()
3789 char location[MAX_LOCATION+20];
3790 sprintf(location, "%s:%d", relativeFilePath, line);
3791 #if defined(__WIN32__)
3792 ChangeCh(location, '/', '\\');
3794 return CopyString(location);
3799 if(relativeFilePath && relativeFilePath[0])
3801 f.Printf(" * %d,%d,%d,%d,%s\n", enabled ? 1 : 0, ignore, level, line, relativeFilePath);
3803 f.Printf(" ~ %s\n", condition.expression);
3812 delete relativeFilePath;
3813 delete absoluteFilePath;
3823 class Watch : struct
3834 f.Printf(" ~ %s\n", expression);
3858 class DebugListItem : struct
3864 struct DebugEvaluationData
3869 uint nextBlockAddress;
3871 DebuggerEvaluationError error;
3874 class CodeLocation : struct
3877 char * absoluteFile;
3880 CodeLocation ::ParseCodeLocation(char * location)
3884 char * colon = null;
3886 char loc[MAX_LOCATION];
3887 strcpy(loc, location);
3888 for(temp = loc; temp = strstr(temp, ":"); temp++)
3896 int line = atoi(colon);
3899 CodeLocation codloc { line = line };
3900 codloc.file = CopyString(loc);
3901 codloc.absoluteFile = ide.workspace.GetAbsolutePathFromRelative(loc);
3913 delete absoluteFile;