Add Debug snapshots and capture of Terminal data flow
Two helper functions introduced: "make debug snapshots" triggered by Ctrl-Cmd-S shortcut and "capture data flow" triggered by Ctrl-Cmd-C shortcut. The first one makes debug dump of current data both in visual and in text buffer, including history lines if they available. The second one mirrors all characters and control sequences that are flowing through the Parser. Both dump and capture files are saved under /var/log folder. That functionality available only if the USE_DEBUG_SNAPSHOTS switch is defined.
This commit is contained in:
parent
238b435a8e
commit
718a28cead
@ -7,6 +7,7 @@
|
||||
|
||||
#include <alloca.h>
|
||||
#include <stdlib.h>
|
||||
#include <fcntl.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <algorithm>
|
||||
@ -111,7 +112,8 @@ BasicTerminalBuffer::BasicTerminalBuffer()
|
||||
fOriginMode(false),
|
||||
fSavedOriginMode(false),
|
||||
fTabStops(NULL),
|
||||
fEncoding(M_UTF8)
|
||||
fEncoding(M_UTF8),
|
||||
fCaptureFile(-1)
|
||||
{
|
||||
}
|
||||
|
||||
@ -121,6 +123,9 @@ BasicTerminalBuffer::~BasicTerminalBuffer()
|
||||
delete fHistory;
|
||||
_FreeLines(fScreen, fHeight);
|
||||
delete[] fTabStops;
|
||||
|
||||
if (fCaptureFile >= 0)
|
||||
close(fCaptureFile);
|
||||
}
|
||||
|
||||
|
||||
@ -255,7 +260,8 @@ BasicTerminalBuffer::SynchronizeWith(const BasicTerminalBuffer* other,
|
||||
destLine->softBreak = sourceLine->softBreak;
|
||||
if (destLine->length > 0) {
|
||||
memcpy(destLine->cells, sourceLine->cells,
|
||||
destLine->length * sizeof(TerminalCell));
|
||||
// destLine->length * sizeof(TerminalCell));
|
||||
fWidth * sizeof(TerminalCell));
|
||||
}
|
||||
} else {
|
||||
// The source line was a history line and has been copied
|
||||
@ -1631,3 +1637,90 @@ BasicTerminalBuffer::_NextChar(TermPos& pos, UTF8Char& c) const
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
#ifdef USE_DEBUG_SNAPSHOTS
|
||||
|
||||
void
|
||||
BasicTerminalBuffer::MakeLinesSnapshots(time_t timeStamp, const char* fileName)
|
||||
{
|
||||
BString str("/var/log/");
|
||||
struct tm* ts = gmtime(&timeStamp);
|
||||
str << ts->tm_hour << ts->tm_min << ts->tm_sec;
|
||||
str << fileName;
|
||||
FILE* fileOut = fopen(str.String(), "w");
|
||||
|
||||
bool dumpHistory = false;
|
||||
do {
|
||||
if (dumpHistory && fHistory == NULL) {
|
||||
fprintf(fileOut, "> History is empty <\n");
|
||||
break;
|
||||
}
|
||||
|
||||
size_t countLines = dumpHistory ? fHistory->Size() : fHeight;
|
||||
fprintf(fileOut, "> %s lines dump begin <\n",
|
||||
dumpHistory ? "History" : "Terminal");
|
||||
|
||||
TerminalLine* lineBuffer = ALLOC_LINE_ON_STACK(fWidth);
|
||||
for (int i = 0; i < countLines; i++) {
|
||||
TerminalLine* line = dumpHistory
|
||||
? fHistory->GetTerminalLineAt(i, lineBuffer)
|
||||
: fScreen[_LineIndex(i)];
|
||||
|
||||
if (line == NULL) {
|
||||
fprintf(fileOut, "line: %ld is NULL!!!\n", i);
|
||||
continue;
|
||||
}
|
||||
|
||||
fprintf(fileOut, "%02d:%02d:%08lx:\n",
|
||||
i, line->length, line->attributes);
|
||||
for (int j = 0; j < line->length; j++)
|
||||
fprintf(fileOut, "%c", line->cells[j].character.bytes[0]);
|
||||
|
||||
fprintf(fileOut, "\n");
|
||||
for (int s = 28; s >= 0; s -= 4) {
|
||||
for (int j = 0; j < fWidth; j++)
|
||||
fprintf(fileOut, "%01lx",
|
||||
(line->cells[j].attributes >> s) & 0x0F);
|
||||
|
||||
fprintf(fileOut, "\n");
|
||||
}
|
||||
|
||||
fprintf(fileOut, "\n");
|
||||
}
|
||||
|
||||
fprintf(fileOut, "> %s lines dump finished <\n",
|
||||
dumpHistory ? "History" : "Terminal");
|
||||
|
||||
} while (dumpHistory = !dumpHistory);
|
||||
|
||||
fclose(fileOut);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
BasicTerminalBuffer::RestartDebugCapture()
|
||||
{
|
||||
if (fCaptureFile >= 0) {
|
||||
close(fCaptureFile);
|
||||
fCaptureFile = -1;
|
||||
return;
|
||||
}
|
||||
|
||||
time_t timeStamp = time(NULL);
|
||||
BString str("/var/log/");
|
||||
struct tm* ts = gmtime(&timeStamp);
|
||||
str << ts->tm_hour << ts->tm_min << ts->tm_sec;
|
||||
str << ".Capture.log";
|
||||
fCaptureFile = open(str.String(), O_CREAT | O_WRONLY);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
BasicTerminalBuffer::CaptureChar(char ch)
|
||||
{
|
||||
if (fCaptureFile >= 0)
|
||||
write(fCaptureFile, &ch, 1);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
@ -104,6 +104,12 @@ public:
|
||||
bool matchWord, TermPos& matchStart,
|
||||
TermPos& matchEnd) const;
|
||||
|
||||
// snapshots and data capture for debugging
|
||||
void MakeLinesSnapshots(time_t timeStamp,
|
||||
const char* fileName);
|
||||
void RestartDebugCapture();
|
||||
/*inline*/ void CaptureChar(char ch);
|
||||
|
||||
// insert chars/lines
|
||||
inline void InsertChar(UTF8Char c, uint32 attributes);
|
||||
void InsertChar(UTF8Char c, uint32 width,
|
||||
@ -220,6 +226,7 @@ protected:
|
||||
bool* fTabStops;
|
||||
|
||||
int fEncoding;
|
||||
int fCaptureFile;
|
||||
|
||||
// listener/dirty region management
|
||||
TerminalBufferDirtyInfo fDirtyInfo;
|
||||
|
@ -46,6 +46,15 @@
|
||||
#include <SupportDefs.h>
|
||||
|
||||
|
||||
// define to get Ctrl-Cmd-S / Ctrl-Cmd-C shortcuts
|
||||
// to get the debug buffers snapshots and control
|
||||
// sequences capture logging
|
||||
#define USE_DEBUG_SNAPSHOTS
|
||||
#ifdef USE_DEBUG_SNAPSHOTS
|
||||
const uint32 SHORTCUT_DEBUG_SNAPSHOTS = 'sdbs';
|
||||
const uint32 SHORTCUT_DEBUG_CAPTURE = 'srdc';
|
||||
#endif
|
||||
|
||||
// Menu Message
|
||||
static const uint32 MENU_SWITCH_TERM = 'MSWT';
|
||||
static const uint32 MENU_NEW_TERM = 'MNTE';
|
||||
|
@ -409,6 +409,11 @@ TermParse::EscParse()
|
||||
}
|
||||
|
||||
//debug_printf("TermParse: char: '%c' (%d), parse state: %d\n", c, c, parsestate[c]);
|
||||
|
||||
#ifdef USE_DEBUG_SNAPSHOTS
|
||||
fBuffer->CaptureChar(c);
|
||||
#endif
|
||||
|
||||
switch (parsestate[c]) {
|
||||
case CASE_PRINT:
|
||||
fBuffer->InsertChar((char)c, fAttr);
|
||||
|
@ -3238,3 +3238,25 @@ void
|
||||
TermView::Listener::NextTermView(TermView* view)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
#ifdef USE_DEBUG_SNAPSHOTS
|
||||
|
||||
void
|
||||
TermView::MakeDebugSnapshots()
|
||||
{
|
||||
BAutolock _(fTextBuffer);
|
||||
time_t timeStamp = time(NULL);
|
||||
fTextBuffer->MakeLinesSnapshots(timeStamp, ".TextBuffer.log");
|
||||
fVisibleTextBuffer->MakeLinesSnapshots(timeStamp, ".VisualTextBuffer.log");
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
TermView::RestartDebugCapture()
|
||||
{
|
||||
BAutolock _(fTextBuffer);
|
||||
fTextBuffer->RestartDebugCapture();
|
||||
}
|
||||
|
||||
#endif
|
||||
|
@ -90,6 +90,9 @@ public:
|
||||
|
||||
void SetMouseClipboard(BClipboard *);
|
||||
|
||||
void MakeDebugSnapshots();
|
||||
void RestartDebugCapture();
|
||||
|
||||
// edit functions
|
||||
void Copy(BClipboard* clipboard);
|
||||
void Paste(BClipboard* clipboard);
|
||||
|
@ -517,6 +517,13 @@ TermWindow::_SetupMenu()
|
||||
AddChild(fMenuBar);
|
||||
|
||||
_UpdateSwitchTerminalsMenuItem();
|
||||
|
||||
#ifdef USE_DEBUG_SNAPSHOTS
|
||||
AddShortcut('S', B_COMMAND_KEY | B_CONTROL_KEY,
|
||||
new BMessage(SHORTCUT_DEBUG_SNAPSHOTS));
|
||||
AddShortcut('C', B_COMMAND_KEY | B_CONTROL_KEY,
|
||||
new BMessage(SHORTCUT_DEBUG_CAPTURE));
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
@ -658,6 +665,16 @@ TermWindow::MessageReceived(BMessage *message)
|
||||
_ActiveTermView()->Paste(be_clipboard);
|
||||
break;
|
||||
|
||||
#ifdef USE_DEBUG_SNAPSHOTS
|
||||
case SHORTCUT_DEBUG_SNAPSHOTS:
|
||||
_ActiveTermView()->MakeDebugSnapshots();
|
||||
break;
|
||||
|
||||
case SHORTCUT_DEBUG_CAPTURE:
|
||||
_ActiveTermView()->RestartDebugCapture();
|
||||
break;
|
||||
#endif
|
||||
|
||||
case B_SELECT_ALL:
|
||||
_ActiveTermView()->SelectAll();
|
||||
break;
|
||||
|
Loading…
Reference in New Issue
Block a user