From 184eafce20c721c56593cf792bfb017812cfa027 Mon Sep 17 00:00:00 2001 From: Linus Dierheimer Date: Sun, 28 Mar 2021 13:02:40 +0200 Subject: [PATCH] better cpu output --- src/common.c | 2 +- src/fastfetch.c | 2 +- src/modules/cpu.c | 136 +++++++++++++++++++++++++++++++++++--------- src/modules/os.c | 2 +- src/util/FFstrbuf.c | 59 ++++++++++++++++++- src/util/FFstrbuf.h | 6 ++ 6 files changed, 177 insertions(+), 30 deletions(-) diff --git a/src/common.c b/src/common.c index 4de891fc0..987c48512 100644 --- a/src/common.c +++ b/src/common.c @@ -115,7 +115,7 @@ void ffParsePropFile(const char* fileName, const char* regex, char* buffer) buffer[0] = '\0'; //If an error occures, this is the indicator char* line = NULL; - size_t len; + size_t len = 0; FILE* file = fopen(fileName, "r"); if(file == NULL) diff --git a/src/fastfetch.c b/src/fastfetch.c index 1b6ad1ad8..48666c036 100644 --- a/src/fastfetch.c +++ b/src/fastfetch.c @@ -232,7 +232,7 @@ static inline void printCommandHelp(const char* command) else if(strcasecmp(command, "terminal-font-format") == 0) constructAndPrintCommandHelpFormat("terminal-font", "{}", 1, "Terminal font name"); else if(strcasecmp(command, "cpu-format") == 0) - constructAndPrintCommandHelpFormat("cpu", "{} ({}) @ {}GHz", 3, "CPU name", "CPU logical core count", "CPU frequency"); + constructAndPrintCommandHelpFormat("cpu", "{2} ({4}) @ {7}GHz", 11, "CPU name", "Prettified CPU name", "CPU Vendor name (Vendor ID)", "CPU logical core count online", "CPU logical core count configured", "CPU physical core count", "frequency bios limit", "frequency scaling max", "frequency scaling min", "frequency info max", "frequency info min"); else if(strcasecmp(command, "gpu-format") == 0) constructAndPrintCommandHelpFormat("gpu", "{} {}", 2, "GPU vendor", "GPU name"); else if(strcasecmp(command, "memory-format") == 0) diff --git a/src/modules/cpu.c b/src/modules/cpu.c index e16421200..2063ede5a 100644 --- a/src/modules/cpu.c +++ b/src/modules/cpu.c @@ -1,53 +1,137 @@ #include "fastfetch.h" +static double getGhz(const char* file) +{ + FF_STRBUF_CREATE(content); + ffGetFileContent(file, &content); + + if(content.length == 0) + return 0; + + uint32_t herz; + if(sscanf(content.chars, "%u", &herz) != 1) + return 0; + + ffStrbufDestroy(&content); + + herz /= 1000; //to MHz + return (double) herz / 1000.0; //to GHz +} + void ffPrintCPU(FFinstance* instance) { if(ffPrintCachedValue(instance, "CPU")) return; - char name[256]; - ffParsePropFile("/proc/cpuinfo", "model name%*s %[^\n]", name); - if(name[0] == '\0') + char name[256]; name[0] = '\0'; + char vendor[256]; vendor[0] = '\0'; + int physicalCores = 0; + + FILE* cpuinfo = fopen("/proc/cpuinfo", "r"); + + char* line = NULL; + size_t len = 0; + + while(getline(&line, &len, cpuinfo) != -1) { - ffPrintError(instance, "CPU", "\"model name%*s %[^\\n]\" not found in \"/proc/cpuinfo\""); - return; + sscanf(line, "model name%*s %[^\n]", name); + sscanf(line, "vendor_id%*s %[^\n]", vendor); + sscanf(line, "cpu cores%*s %i", &physicalCores); + + //Stop after the first CPU + if(strstr(line, "flags") != NULL) + break; } - FILE* frequencyFile = fopen("/sys/devices/system/cpu/cpu0/cpufreq/scaling_max_freq", "r"); - if(frequencyFile == NULL) - { - ffPrintError(instance, "CPU", "fopen(\"/sys/devices/system/cpu/cpu0/cpufreq/scaling_max_freq\", \"r\") == NULL"); - return; - } - uint32_t frequency; - int scanned = fscanf(frequencyFile, "%u", &frequency); - if(scanned != 1) - { - ffPrintError(instance, "CPU", "fscanf(frequencyFile, \"%s\", frequency) != 1"); - return; - } - fclose(frequencyFile); + if(line != NULL) + free(line); - frequency /= 1000; //to MHz - double ghz = (double) frequency / 1000.0; //to GHz + fclose(cpuinfo); - int numProcs = get_nprocs(); + FFstrbuf namePretty; + ffStrbufInitA(&namePretty, 256); + ffStrbufAppendS(&namePretty, name); + ffStrbufRemoveStrings(&namePretty, 11, + "(R)", "(r)", "(TM)", "(tm)", " CPU", " FPU", " Processor", " Dual-Core", " Quad-Core", " Six-Core", " Eight-Core" + ); + ffStrbufLimitLength(&namePretty, ffStrbufLastIndexC(&namePretty, '@')); //Cut the speed output in the name as we append our own + ffStrbufTrimRight(&namePretty, ' '); //If we removed the @ in previous step there was most likely a space before it + + double biosLimit = getGhz("/sys/devices/system/cpu/cpu0/cpufreq/bios_limit"); + double scalingMaxFreq = getGhz("/sys/devices/system/cpu/cpu0/cpufreq/scaling_max_freq"); + double scalingMinFreq = getGhz("/sys/devices/system/cpu/cpu0/cpufreq/scaling_min_freq"); + double infoMaxFreq = getGhz("/sys/devices/system/cpu/cpu0/cpufreq/cpuinfo_max_freq"); + double infoMinFreq = getGhz("/sys/devices/system/cpu/cpu0/cpufreq/cpuinfo_min_freq"); + + int numProcsOnline = get_nprocs(); + int numProcsAvailable = get_nprocs_conf(); FF_STRBUF_CREATE(cpu); if(instance->config.cpuFormat.length == 0) { - ffStrbufSetF(&cpu, "%s (%i) @ %.9gGHz", name, numProcs, ghz); + //The current get_nprocs* returns 1 on failure. It also makes no sense to have a (1) as count + int numProcs = numProcsOnline; + if(numProcs <= 1) + numProcs = numProcsAvailable; + if(numProcs <= 1) + numProcs = physicalCores; + + double ghz = biosLimit; + if(ghz == 0) + ghz = scalingMaxFreq; + if(ghz == 0) + ghz = infoMaxFreq; + if(ghz == 0) + ghz = scalingMinFreq; + if(ghz == 0) + ghz = infoMinFreq; + + + if(namePretty.length > 0) + ffStrbufAppend(&cpu, &namePretty); + else if(name[0] != '\0') + ffStrbufAppendS(&cpu, name); + else if(vendor[0] != '\0') + { + ffStrbufAppendS(&cpu, vendor); + ffStrbufAppendS(&cpu, " unknown processor"); + } + else if(numProcs > 1 || ghz > 0) + ffStrbufAppendS(&cpu, " unknwon processor"); + else + { + ffPrintError(instance, "CPU", "No CPU info found in /proc/cpuinfo"); + ffStrbufDestroy(&cpu); + ffStrbufDestroy(&namePretty); + return; + } + + if(numProcs > 1) + ffStrbufAppendF(&cpu, " (%i)", numProcs); + + if(ghz > 0) + ffStrbufAppendF(&cpu, " @ %.9gGHz", ghz); } else { - ffParseFormatString(&cpu, &instance->config.cpuFormat, 3, + ffParseFormatString(&cpu, &instance->config.cpuFormat, 11, (FFformatarg){FF_FORMAT_ARG_TYPE_STRING, name}, - (FFformatarg){FF_FORMAT_ARG_TYPE_INT, &numProcs}, - (FFformatarg){FF_FORMAT_ARG_TYPE_DOUBLE, &ghz} + (FFformatarg){FF_FORMAT_ARG_TYPE_STRBUF, &namePretty}, + (FFformatarg){FF_FORMAT_ARG_TYPE_STRING, vendor}, + (FFformatarg){FF_FORMAT_ARG_TYPE_INT, &numProcsOnline}, + (FFformatarg){FF_FORMAT_ARG_TYPE_INT, &numProcsAvailable}, + (FFformatarg){FF_FORMAT_ARG_TYPE_INT, &physicalCores}, + (FFformatarg){FF_FORMAT_ARG_TYPE_DOUBLE, &biosLimit}, + (FFformatarg){FF_FORMAT_ARG_TYPE_DOUBLE, &scalingMaxFreq}, + (FFformatarg){FF_FORMAT_ARG_TYPE_DOUBLE, &scalingMinFreq}, + (FFformatarg){FF_FORMAT_ARG_TYPE_DOUBLE, &infoMaxFreq}, + (FFformatarg){FF_FORMAT_ARG_TYPE_DOUBLE, &infoMinFreq} ); } ffPrintAndSaveCachedValue(instance, "CPU", &cpu); ffStrbufDestroy(&cpu); + + ffStrbufDestroy(&namePretty); } diff --git a/src/modules/os.c b/src/modules/os.c index 42238d682..ec4cea1ae 100644 --- a/src/modules/os.c +++ b/src/modules/os.c @@ -25,7 +25,7 @@ void ffPrintOS(FFinstance* instance) osRelease = fopen("/usr/lib/os-release", "r"); char* line = NULL; - size_t len; + size_t len = 0; while (getline(&line, &len, osRelease) != -1) { diff --git a/src/util/FFstrbuf.c b/src/util/FFstrbuf.c index a9235ae7f..e35a20897 100644 --- a/src/util/FFstrbuf.c +++ b/src/util/FFstrbuf.c @@ -278,7 +278,7 @@ void ffStrbufTrimLeft(FFstrbuf* strbuf, char c) if(index == 0) return; - memcpy(strbuf->chars, strbuf->chars + index, index); + memmove(strbuf->chars, strbuf->chars + index, index); strbuf->length -= index; } @@ -296,6 +296,63 @@ void ffStrbufTrim(FFstrbuf* strbuf, char c) ffStrbufTrimLeft(strbuf, c); } +static bool strbufRemoveTest(FFstrbuf* strbuf, uint32_t i, const char* substr) +{ + uint32_t k; + for(k = 0; substr[k] != '\0'; k++) + { + if(i + k > strbuf->length) + return false; + + if(strbuf->chars[i + k] != substr[k]) + return false; + } + + memmove(&strbuf->chars[i], &strbuf->chars[i + k], strbuf->length - i - k); + strbuf->length -= k; + strbuf->chars[strbuf->length] = '\0'; + return true; +} + +void ffStrbufRemoveStrings(FFstrbuf* strbuf, uint32_t numStrings, ...) +{ + const char* strings[numStrings]; + + va_list argp; + va_start(argp, numStrings); + + for(uint32_t i = 0; i < numStrings; i++) + strings[i] = va_arg(argp, const char*); + + va_end(argp); + + for(uint32_t i = 0; i < strbuf->length; i++) + { + for(uint32_t k = 0; k < numStrings; k++) + while(strbufRemoveTest(strbuf, i, strings[k])); + } +} + +uint32_t ffStrbufLastIndexC(FFstrbuf* strbuf, const char c) +{ + //We need to loop one higher than the actual index, because uint32_t is guranteed to be >= 0, so this statement would always be true + for(uint32_t i = strbuf->length; i > 0; i--) + { + if(strbuf->chars[i - 1] == c) + return i - 1; + } + return strbuf->length; +} + +void ffStrbufLimitLength(FFstrbuf* strbuf, uint32_t length) +{ + if(strbuf->length <= length) + return; + + strbuf->length = length; + strbuf->chars[strbuf->length] = '\0'; +} + void ffStrbufDestroy(FFstrbuf* strbuf) { free(strbuf->chars); diff --git a/src/util/FFstrbuf.h b/src/util/FFstrbuf.h index 4ef4f5679..f3cf2c2f5 100644 --- a/src/util/FFstrbuf.h +++ b/src/util/FFstrbuf.h @@ -66,6 +66,12 @@ void ffStrbufTrimLeft(FFstrbuf* strbuf, char c); void ffStrbufTrimRight(FFstrbuf* strbuf, char c); void ffStrbufTrim(FFstrbuf* strbuf, char c); +void ffStrbufRemoveStrings(FFstrbuf* strbuf, uint32_t numStrings, ...); + +uint32_t ffStrbufLastIndexC(FFstrbuf* strbuf, const char c); + +void ffStrbufLimitLength(FFstrbuf* strbuf, uint32_t length); + void ffStrbufDestroy(FFstrbuf* strbuf); #endif