mirror of https://github.com/xzeldon/htop.git
Refactor command string creation
Hopefully this patch makes it a bit more approachable how it's done.
This commit is contained in:
parent
27b36dab1a
commit
46ee28e897
|
@ -335,17 +335,24 @@ returned by LinuxProcess_getCommandStr() for searching, sorting and filtering.
|
||||||
*/
|
*/
|
||||||
void LinuxProcess_makeCommandStr(Process* this) {
|
void LinuxProcess_makeCommandStr(Process* this) {
|
||||||
LinuxProcess *lp = (LinuxProcess *)this;
|
LinuxProcess *lp = (LinuxProcess *)this;
|
||||||
|
LinuxProcessMergedCommand *mc = &lp->mergedCommand;
|
||||||
|
|
||||||
bool showMergedCommand = this->settings->showMergedCommand;
|
bool showMergedCommand = this->settings->showMergedCommand;
|
||||||
bool showProgramPath = this->settings->showProgramPath;
|
bool showProgramPath = this->settings->showProgramPath;
|
||||||
bool searchCommInCmdline = this->settings->findCommInCmdline;
|
bool searchCommInCmdline = this->settings->findCommInCmdline;
|
||||||
bool stripExeFromCmdline = this->settings->stripExeFromCmdline;
|
bool stripExeFromCmdline = this->settings->stripExeFromCmdline;
|
||||||
|
|
||||||
/* lp->mergedCommand.str needs to be remade only if there is a change in its
|
/* lp->mergedCommand.str needs updating only if its state or contents changed.
|
||||||
* state consisting of the relevant settings and the three fields cmdline,
|
* Its content is based on the fields cmdline, comm, and exe. */
|
||||||
* comm and exe */
|
if (
|
||||||
if (showMergedCommand == lp->mergedCommand.prevMergeSet && showProgramPath == lp->mergedCommand.prevPathSet &&
|
mc->prevMergeSet == showMergedCommand &&
|
||||||
searchCommInCmdline == lp->mergedCommand.prevCommSet && stripExeFromCmdline == lp->mergedCommand.prevCmdlineSet &&
|
mc->prevPathSet == showProgramPath &&
|
||||||
!lp->mergedCommand.cmdlineChanged && !lp->mergedCommand.commChanged && !lp->mergedCommand.exeChanged) {
|
mc->prevCommSet == searchCommInCmdline &&
|
||||||
|
mc->prevCmdlineSet == stripExeFromCmdline &&
|
||||||
|
!mc->cmdlineChanged &&
|
||||||
|
!mc->commChanged &&
|
||||||
|
!mc->exeChanged
|
||||||
|
) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -354,107 +361,138 @@ void LinuxProcess_makeCommandStr(Process* this) {
|
||||||
const char *SEPARATOR = CRT_treeStr[TREE_STR_VERT];
|
const char *SEPARATOR = CRT_treeStr[TREE_STR_VERT];
|
||||||
const int SEPARATOR_LEN = strlen(SEPARATOR);
|
const int SEPARATOR_LEN = strlen(SEPARATOR);
|
||||||
|
|
||||||
if (lp->mergedCommand.cmdlineChanged || lp->mergedCommand.commChanged || lp->mergedCommand.exeChanged) {
|
/* Check for any changed fields since we last built this string */
|
||||||
free(lp->mergedCommand.str);
|
if (mc->cmdlineChanged || mc->commChanged || mc->exeChanged) {
|
||||||
/* Also accomodate two field separators and a NUL */
|
free(mc->str);
|
||||||
lp->mergedCommand.str = xMalloc(lp->mergedCommand.maxLen + 2*SEPARATOR_LEN + 1);
|
/* Accomodate the column text, two field separators and terminating NUL */
|
||||||
|
mc->str = xCalloc(1, mc->maxLen + 2*SEPARATOR_LEN + 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
lp->mergedCommand.prevMergeSet = showMergedCommand;
|
/* Preserve the settings used in this run */
|
||||||
lp->mergedCommand.prevPathSet = showProgramPath;
|
mc->prevMergeSet = showMergedCommand;
|
||||||
lp->mergedCommand.prevCommSet = searchCommInCmdline;
|
mc->prevPathSet = showProgramPath;
|
||||||
lp->mergedCommand.prevCmdlineSet = stripExeFromCmdline;
|
mc->prevCommSet = searchCommInCmdline;
|
||||||
lp->mergedCommand.cmdlineChanged = false;
|
mc->prevCmdlineSet = stripExeFromCmdline;
|
||||||
lp->mergedCommand.commChanged = false;
|
|
||||||
lp->mergedCommand.exeChanged = false;
|
/* Mark everything as unchanged */
|
||||||
|
mc->cmdlineChanged = false;
|
||||||
|
mc->commChanged = false;
|
||||||
|
mc->exeChanged = false;
|
||||||
|
|
||||||
|
/* Clear any separators */
|
||||||
|
mc->sep1 = 0;
|
||||||
|
mc->sep2 = 0;
|
||||||
|
|
||||||
|
/* Clear any highlighting locations */
|
||||||
|
mc->baseStart = 0;
|
||||||
|
mc->baseEnd = 0;
|
||||||
|
mc->commStart = 0;
|
||||||
|
mc->commEnd = 0;
|
||||||
|
|
||||||
char *str;
|
|
||||||
char *strStart = lp->mergedCommand.str;
|
|
||||||
const char *cmdline = this->comm;
|
const char *cmdline = this->comm;
|
||||||
const char *procExe = lp->procExe;
|
const char *procExe = lp->procExe;
|
||||||
const char *procComm = lp->procComm;
|
const char *procComm = lp->procComm;
|
||||||
|
|
||||||
|
char *strStart = mc->str;
|
||||||
|
char *str = strStart;
|
||||||
|
|
||||||
int cmdlineBasenameOffset = lp->procCmdlineBasenameOffset;
|
int cmdlineBasenameOffset = lp->procCmdlineBasenameOffset;
|
||||||
|
|
||||||
if (!showMergedCommand || !procExe || !procComm) { /* fall back to cmdline */
|
if (!showMergedCommand || !procExe || !procComm) { /* fall back to cmdline */
|
||||||
if (showProgramPath) {
|
if (showProgramPath) {
|
||||||
(void) stpcpyWithNewlineConversion(strStart, cmdline);
|
(void) stpcpyWithNewlineConversion(strStart, cmdline);
|
||||||
lp->mergedCommand.baseStart = cmdlineBasenameOffset;
|
mc->baseStart = cmdlineBasenameOffset;
|
||||||
lp->mergedCommand.baseEnd = lp->procCmdlineBasenameEnd;
|
mc->baseEnd = lp->procCmdlineBasenameEnd;
|
||||||
} else {
|
} else {
|
||||||
(void) stpcpyWithNewlineConversion(strStart, cmdline + cmdlineBasenameOffset);
|
(void) stpcpyWithNewlineConversion(strStart, cmdline + cmdlineBasenameOffset);
|
||||||
lp->mergedCommand.baseStart = 0;
|
mc->baseStart = 0;
|
||||||
lp->mergedCommand.baseEnd = lp->procCmdlineBasenameEnd - cmdlineBasenameOffset;
|
mc->baseEnd = lp->procCmdlineBasenameEnd - cmdlineBasenameOffset;
|
||||||
}
|
}
|
||||||
lp->mergedCommand.commEnd = 0;
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
int commStart = 0;
|
|
||||||
int commEnd = 0;
|
|
||||||
int exeBasenameOffset = lp->procExeBasenameOffset;
|
|
||||||
int exeLen = lp->procExeLen;
|
int exeLen = lp->procExeLen;
|
||||||
int exeBaseLen = exeLen - exeBasenameOffset;
|
int exeBasenameOffset = lp->procExeBasenameOffset;
|
||||||
bool commInCmdline = false;
|
int exeBasenameLen = exeLen - exeBasenameOffset;
|
||||||
|
|
||||||
/* Start with copying exe */
|
/* Start with copying exe */
|
||||||
if (showProgramPath) {
|
if (showProgramPath) {
|
||||||
str = stpcpy(strStart, procExe);
|
str = stpcpy(str, procExe);
|
||||||
lp->mergedCommand.baseStart = exeBasenameOffset;
|
mc->baseStart = exeBasenameOffset;
|
||||||
lp->mergedCommand.baseEnd = exeLen;
|
mc->baseEnd = exeLen;
|
||||||
} else {
|
} else {
|
||||||
str = stpcpy(strStart, procExe + exeBasenameOffset);
|
str = stpcpy(str, procExe + exeBasenameOffset);
|
||||||
lp->mergedCommand.baseStart = 0;
|
mc->baseStart = 0;
|
||||||
lp->mergedCommand.baseEnd = exeBaseLen;
|
mc->baseEnd = exeBasenameLen;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
mc->sep1 = 0;
|
||||||
|
mc->sep2 = 0;
|
||||||
|
|
||||||
|
int commStart = 0;
|
||||||
|
int commEnd = 0;
|
||||||
|
bool commInCmdline = false;
|
||||||
|
|
||||||
/* Try to match procComm with procExe's basename: This is reliable (predictable) */
|
/* Try to match procComm with procExe's basename: This is reliable (predictable) */
|
||||||
if (strncmp(procExe + exeBasenameOffset, procComm, TASK_COMM_LEN - 1) == 0) {
|
if (strncmp(procExe + exeBasenameOffset, procComm, TASK_COMM_LEN - 1) == 0) {
|
||||||
commStart = lp->mergedCommand.baseStart;
|
commStart = mc->baseStart;
|
||||||
commEnd = lp->mergedCommand.baseEnd;
|
commEnd = mc->baseEnd;
|
||||||
} else if (searchCommInCmdline) {
|
} else if (searchCommInCmdline) {
|
||||||
/* commStart/commEnd will be adjusted later along with cmdline */
|
/* commStart/commEnd will be adjusted later along with cmdline */
|
||||||
commInCmdline = findCommInCmdline(procComm, cmdline, cmdlineBasenameOffset, &commStart, &commEnd);
|
commInCmdline = findCommInCmdline(procComm, cmdline, cmdlineBasenameOffset, &commStart, &commEnd);
|
||||||
}
|
}
|
||||||
|
|
||||||
int matchLen = matchCmdlinePrefixWithExeSuffix(cmdline, cmdlineBasenameOffset,
|
int matchLen = matchCmdlinePrefixWithExeSuffix(cmdline, cmdlineBasenameOffset, procExe, exeBasenameOffset, exeBasenameLen);
|
||||||
procExe, exeBasenameOffset, exeBaseLen);
|
|
||||||
/* Note: commStart, commEnd are offsets into RichString. But the multibyte
|
/* Note: commStart, commEnd are offsets into RichString. But the multibyte
|
||||||
* separator (with size SEPARATOR_LEN) has size 1 in RichString. The offset
|
* separator (with size SEPARATOR_LEN) has size 1 in RichString. The offset
|
||||||
* adjustments below reflect this. */
|
* adjustments below reflect this. */
|
||||||
if (commEnd) {
|
if (commEnd) {
|
||||||
if (matchLen) { /* strip the matched exe prefix */
|
mc->unmatchedExe = !matchLen;
|
||||||
lp->mergedCommand.unmatchedExe = false;
|
|
||||||
|
if (matchLen) {
|
||||||
|
/* strip the matched exe prefix */
|
||||||
cmdline += matchLen;
|
cmdline += matchLen;
|
||||||
|
|
||||||
if (commInCmdline) {
|
if (commInCmdline) {
|
||||||
commStart += str - strStart - matchLen;
|
commStart += str - strStart - matchLen;
|
||||||
commEnd += str - strStart - matchLen;
|
commEnd += str - strStart - matchLen;
|
||||||
}
|
}
|
||||||
} else { /* cmdline will be a separate field */
|
} else {
|
||||||
lp->mergedCommand.unmatchedExe = true;
|
/* cmdline will be a separate field */
|
||||||
|
mc->sep1 = str - strStart;
|
||||||
str = stpcpy(str, SEPARATOR);
|
str = stpcpy(str, SEPARATOR);
|
||||||
|
|
||||||
if (commInCmdline) {
|
if (commInCmdline) {
|
||||||
commStart += str - strStart - SEPARATOR_LEN + 1;
|
commStart += str - strStart - SEPARATOR_LEN + 1;
|
||||||
commEnd += str - strStart - SEPARATOR_LEN + 1;
|
commEnd += str - strStart - SEPARATOR_LEN + 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
lp->mergedCommand.separateComm = false; /* procComm merged */
|
|
||||||
|
mc->separateComm = false; /* procComm merged */
|
||||||
} else {
|
} else {
|
||||||
|
mc->sep1 = str - strStart;
|
||||||
str = stpcpy(str, SEPARATOR);
|
str = stpcpy(str, SEPARATOR);
|
||||||
|
|
||||||
commStart = str - strStart - SEPARATOR_LEN + 1;
|
commStart = str - strStart - SEPARATOR_LEN + 1;
|
||||||
str = stpcpy(str, procComm);
|
str = stpcpy(str, procComm);
|
||||||
commEnd = str - strStart - SEPARATOR_LEN + 1; /* or commStart + strlen(procComm) */
|
commEnd = str - strStart - SEPARATOR_LEN + 1; /* or commStart + strlen(procComm) */
|
||||||
|
|
||||||
|
mc->unmatchedExe = !matchLen;
|
||||||
|
|
||||||
if (matchLen) {
|
if (matchLen) {
|
||||||
lp->mergedCommand.unmatchedExe = false;
|
|
||||||
if (stripExeFromCmdline) {
|
if (stripExeFromCmdline) {
|
||||||
cmdline += matchLen;
|
cmdline += matchLen;
|
||||||
}
|
}
|
||||||
} else {
|
|
||||||
lp->mergedCommand.unmatchedExe = true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (*cmdline) {
|
if (*cmdline) {
|
||||||
|
mc->sep2 = str - strStart - SEPARATOR_LEN + 1;
|
||||||
str = stpcpy(str, SEPARATOR);
|
str = stpcpy(str, SEPARATOR);
|
||||||
}
|
}
|
||||||
lp->mergedCommand.separateComm = true; /* procComm a separate field */
|
|
||||||
|
mc->separateComm = true; /* procComm a separate field */
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Display cmdline if it hasn't been consumed by procExe */
|
/* Display cmdline if it hasn't been consumed by procExe */
|
||||||
|
@ -462,56 +500,58 @@ void LinuxProcess_makeCommandStr(Process* this) {
|
||||||
(void) stpcpyWithNewlineConversion(str, cmdline);
|
(void) stpcpyWithNewlineConversion(str, cmdline);
|
||||||
}
|
}
|
||||||
|
|
||||||
lp->mergedCommand.commStart = commStart;
|
mc->commStart = commStart;
|
||||||
lp->mergedCommand.commEnd = commEnd;
|
mc->commEnd = commEnd;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void LinuxProcess_writeCommand(const Process* this, int attr, int baseAttr, RichString* str) {
|
static void LinuxProcess_writeCommand(const Process* this, int attr, int baseAttr, RichString* str) {
|
||||||
const LinuxProcess *lp = (const LinuxProcess *)this;
|
const LinuxProcess *lp = (const LinuxProcess *)this;
|
||||||
|
const LinuxProcessMergedCommand *mc = &lp->mergedCommand;
|
||||||
|
|
||||||
int strStart = RichString_size(str);
|
int strStart = RichString_size(str);
|
||||||
|
|
||||||
int baseStart = strStart + lp->mergedCommand.baseStart;
|
int baseStart = strStart + lp->mergedCommand.baseStart;
|
||||||
int baseEnd = strStart + lp->mergedCommand.baseEnd;
|
int baseEnd = strStart + lp->mergedCommand.baseEnd;
|
||||||
|
int commStart = strStart + lp->mergedCommand.commStart;
|
||||||
|
int commEnd = strStart + lp->mergedCommand.commEnd;
|
||||||
|
|
||||||
|
int commAttr = CRT_colors[Process_isUserlandThread(this) ? PROCESS_THREAD_COMM : PROCESS_COMM];
|
||||||
|
|
||||||
bool highlightBaseName = this->settings->highlightBaseName;
|
bool highlightBaseName = this->settings->highlightBaseName;
|
||||||
|
|
||||||
RichString_append(str, attr, lp->mergedCommand.str);
|
RichString_append(str, attr, lp->mergedCommand.str);
|
||||||
|
|
||||||
if (lp->mergedCommand.commEnd) {
|
if (lp->mergedCommand.commEnd) {
|
||||||
int commStart = strStart + lp->mergedCommand.commStart;
|
|
||||||
int commEnd = strStart + lp->mergedCommand.commEnd;
|
|
||||||
int commAttr = CRT_colors[Process_isUserlandThread(this) ? PROCESS_THREAD_COMM : PROCESS_COMM];
|
|
||||||
if (lp->mergedCommand.separateComm) {
|
if (lp->mergedCommand.separateComm) {
|
||||||
RichString_setAttrn(str, commAttr, commStart, commEnd - 1);
|
RichString_setAttrn(str, commAttr, commStart, commEnd - 1);
|
||||||
if (lp->mergedCommand.unmatchedExe) {
|
} else if (commStart == baseStart && highlightBaseName) {
|
||||||
RichString_setAttrn(str, CRT_colors[FAILED_READ], commEnd, commEnd);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
/* If it was matched with procExe's basename, make it bold if needed */
|
/* If it was matched with procExe's basename, make it bold if needed */
|
||||||
if (commStart == baseStart && highlightBaseName) {
|
|
||||||
if (commEnd > baseEnd) {
|
if (commEnd > baseEnd) {
|
||||||
RichString_setAttrn(str, A_BOLD | baseAttr, commStart, baseEnd - 1);
|
RichString_setAttrn(str, A_BOLD | baseAttr, baseStart, baseEnd - 1);
|
||||||
baseStart = baseEnd;
|
RichString_setAttrn(str, A_BOLD | commAttr, baseEnd, commEnd - 1);
|
||||||
RichString_setAttrn(str, commAttr, baseStart, commEnd - 1);
|
|
||||||
} else if (commEnd < baseEnd) {
|
} else if (commEnd < baseEnd) {
|
||||||
RichString_setAttrn(str, A_BOLD | commAttr, commStart, commEnd - 1);
|
RichString_setAttrn(str, A_BOLD | commAttr, commStart, commEnd - 1);
|
||||||
baseStart = commEnd;
|
RichString_setAttrn(str, A_BOLD | baseAttr, commEnd, baseEnd - 1);
|
||||||
// Remainder marked baseAttr at end of function
|
|
||||||
} else {
|
} else {
|
||||||
// Actually should be highlighted commAttr, but marked baseAttr to reduce visual noise
|
// Actually should be highlighted commAttr, but marked baseAttr to reduce visual noise
|
||||||
RichString_setAttrn(str, A_BOLD | baseAttr, commStart, commEnd - 1);
|
RichString_setAttrn(str, A_BOLD | baseAttr, commStart, commEnd - 1);
|
||||||
baseStart = commEnd;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
baseStart = baseEnd;
|
||||||
} else {
|
} else {
|
||||||
RichString_setAttrn(str, commAttr, commStart, commEnd - 1);
|
RichString_setAttrn(str, commAttr, commStart, commEnd - 1);
|
||||||
}
|
}
|
||||||
if (lp->mergedCommand.unmatchedExe) {
|
|
||||||
RichString_setAttrn(str, CRT_colors[FAILED_READ], baseEnd, baseEnd);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (baseStart < baseEnd && highlightBaseName) {
|
if (baseStart < baseEnd && highlightBaseName) {
|
||||||
RichString_setAttrn(str, baseAttr, baseStart, baseEnd - 1);
|
RichString_setAttrn(str, baseAttr, baseStart, baseEnd - 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (mc->sep1)
|
||||||
|
RichString_setAttrn(str, CRT_colors[FAILED_READ], strStart + mc->sep1, strStart + mc->sep1);
|
||||||
|
if (mc->sep2)
|
||||||
|
RichString_setAttrn(str, CRT_colors[FAILED_READ], strStart + mc->sep2, strStart + mc->sep2);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void LinuxProcess_writeCommandField(const Process *this, RichString *str, char *buffer, int n, int attr) {
|
static void LinuxProcess_writeCommandField(const Process *this, RichString *str, char *buffer, int n, int attr) {
|
||||||
|
|
|
@ -111,6 +111,8 @@ typedef struct LinuxProcessMergedCommand_ {
|
||||||
int baseEnd; /* basename's end offset */
|
int baseEnd; /* basename's end offset */
|
||||||
int commStart; /* comm's start offset */
|
int commStart; /* comm's start offset */
|
||||||
int commEnd; /* comm's end offset */
|
int commEnd; /* comm's end offset */
|
||||||
|
int sep1; /* first field separator, used if non-zero */
|
||||||
|
int sep2; /* second field separator, used if non-zero */
|
||||||
bool separateComm; /* whether comm is a separate field */
|
bool separateComm; /* whether comm is a separate field */
|
||||||
bool unmatchedExe; /* whether exe matched with cmdline */
|
bool unmatchedExe; /* whether exe matched with cmdline */
|
||||||
bool cmdlineChanged; /* whether cmdline changed */
|
bool cmdlineChanged; /* whether cmdline changed */
|
||||||
|
|
Loading…
Reference in New Issue