besides adding output for the voltage ranges, this patch also changes various aspects of the -L output: - sizes are right aligned now with a fixed length of 5 - space between columns is selectable with a constant - test results are always shown in the same column ("PR" and " R" instead of "PR" and "R ") - vendor and device names are split on a delimiter (currently '/') and spread over mutliple lines but only if the tokens are not too short. all other columns are printed on the first line of a chip. - voltage ranges are printed in verbose mode only
it also gets rid of POS_PRINT and digits
Signed-off-by: Stefan Tauner stefan.tauner@student.tuwien.ac.at --- print.c | 273 ++++++++++++++++++++++++++++++++++++++++++++++++++------------- 1 files changed, 216 insertions(+), 57 deletions(-)
diff --git a/print.c b/print.c index b9f7a43..3f1fb3a 100644 --- a/print.c +++ b/print.c @@ -59,40 +59,68 @@ char *flashbuses_to_text(enum chipbustype bustype) return ret; }
-#define POS_PRINT(x) do { pos += strlen(x); msg_ginfo(x); } while (0) - -static int digits(int n) -{ - int i; - - if (!n) - return 1; - - for (i = 0; n; ++i) - n /= 10; - - return i; -} - static void print_supported_chips(void) { - int okcol = 0, pos = 0, i, chipcount = 0; + const char *delim = "/"; + const int mintoklen = 5; + const int border = 2; + int i, chipcount = 0; int maxvendorlen = strlen("Vendor") + 1; int maxchiplen = strlen("Device") + 1; + int maxtypelen = strlen("Type") + 1; const struct flashchip *f; char *s; + char *tmpven, *tmpdev; + int tmpvenlen, tmpdevlen, curvenlen, curdevlen;
+ /* calculate maximum column widths and by iterating over all chips */ for (f = flashchips; f->name != NULL; f++) { /* Ignore "unknown XXXX SPI chip" entries. */ if (!strncmp(f->name, "unknown", 7)) continue; chipcount++; - maxvendorlen = max(maxvendorlen, strlen(f->vendor)); - maxchiplen = max(maxchiplen, strlen(f->name)); + + /* Find maximum vendor length (respecting line splitting). */ + tmpven = (char *)f->vendor; + do { + /* and take minimum token lengths into account */ + tmpvenlen = 0; + do { + tmpvenlen += strcspn(tmpven, delim); + /* skip to the address after the first token */ + tmpven += tmpvenlen; + if (tmpven[0] == '\0') + break; + tmpven++; + } while (tmpvenlen < mintoklen); + maxvendorlen = max(maxvendorlen, tmpvenlen); + if (tmpven[0] == '\0') + break; + } while (1); + + /* same for device name */ + tmpdev = (char *)f->name; + do { + tmpdevlen = 0; + do { + tmpdevlen += strcspn(tmpdev, delim); + tmpdev += tmpdevlen; + if (tmpdev[0] == '\0') + break; + tmpdev++; + } while (tmpdevlen < mintoklen); + maxchiplen = max(maxchiplen, tmpdevlen); + if (tmpdev[0] == '\0') + break; + } while (1); + + s = flashbuses_to_text(f->bustype); + maxtypelen = max(maxtypelen, strlen(s)); + free(s); } - maxvendorlen++; - maxchiplen++; - okcol = maxvendorlen + maxchiplen; + maxvendorlen += border; + maxchiplen += border; + maxtypelen += border;
msg_ginfo("Supported flash chips (total: %d):\n\n", chipcount); msg_ginfo("Vendor"); @@ -102,10 +130,35 @@ static void print_supported_chips(void) for (i = strlen("Device"); i < maxchiplen; i++) msg_ginfo(" ");
- msg_ginfo("Tested Known Size/kB: Type:\n"); - for (i = 0; i < okcol; i++) + msg_ginfo("Test"); + for (i = 0; i < border; i++) + msg_ginfo(" "); + msg_ginfo("Known"); + for (i = 0; i < border; i++) + msg_ginfo(" "); + msg_ginfo(" Size"); + for (i = 0; i < border; i++) + msg_ginfo(" "); + + msg_ginfo("Type"); + for (i = strlen("Type"); i < maxtypelen; i++) + msg_ginfo(" "); + msg_gdbg("Voltage"); + msg_ginfo("\n"); + + for (i = 0; i < maxvendorlen + maxchiplen; i++) + msg_ginfo(" "); + msg_ginfo("OK "); + for (i = 0; i < border; i++) + msg_ginfo(" "); + msg_ginfo("Broken"); + for (i = 0; i < border; i++) msg_ginfo(" "); - msg_ginfo("OK Broken\n\n"); + msg_ginfo("[kB]"); + for (i = 0; i < border + maxtypelen; i++) + msg_ginfo(" "); + msg_gdbg("range [V]"); + msg_ginfo("\n\n"); msg_ginfo("(P = PROBE, R = READ, E = ERASE, W = WRITE)\n\n");
for (f = flashchips; f->name != NULL; f++) { @@ -113,50 +166,156 @@ static void print_supported_chips(void) if (!strncmp(f->name, "unknown", 7)) continue;
- msg_ginfo("%s", f->vendor); - for (i = strlen(f->vendor); i < maxvendorlen; i++) - msg_ginfo(" "); - msg_ginfo("%s", f->name); - for (i = strlen(f->name); i < maxchiplen; i++) - msg_ginfo(" "); - - pos = maxvendorlen + maxchiplen; - if ((f->tested & TEST_OK_MASK)) { - if ((f->tested & TEST_OK_PROBE)) - POS_PRINT("P "); - if ((f->tested & TEST_OK_READ)) - POS_PRINT("R "); - if ((f->tested & TEST_OK_ERASE)) - POS_PRINT("E "); - if ((f->tested & TEST_OK_WRITE)) - POS_PRINT("W "); + /* support for multiline vendor names: + * - make a copy of the original vendor name + * - use strok to put the first token in tmpven + * - keep track of the length of all tokens on the current line + * for ' '-padding in curvenlen + * - check if additional tokens should be printed on the current + * line + * - after all other values are printed print the surplus tokens + * on fresh lines + */ + tmpven = malloc(strlen(f->vendor) + 1); + if (tmpven == NULL) { + msg_gerr("Out of memory!\n"); + exit(1); } - while (pos < okcol + 9) { + strcpy(tmpven, f->vendor); + + tmpven = strtok(tmpven, delim); + msg_ginfo("%s", tmpven); + curvenlen = strlen(tmpven); + while ((tmpven = strtok(NULL, delim)) != NULL) { + msg_ginfo("%s", delim); + curvenlen++; + tmpvenlen = strlen(tmpven); + if (tmpvenlen >= mintoklen) + break; /* big enough to be on its own line */ + msg_ginfo("%s", tmpven); + curvenlen += tmpvenlen; + } + + for (i = curvenlen; i < maxvendorlen; i++) msg_ginfo(" "); - pos++; + + /* support for multiline device names as above */ + tmpdev = malloc(strlen(f->name) + 1); + if (tmpdev == NULL) { + msg_gerr("Out of memory!\n"); + exit(1); } - if ((f->tested & TEST_BAD_MASK)) { - if ((f->tested & TEST_BAD_PROBE)) - POS_PRINT("P "); - if ((f->tested & TEST_BAD_READ)) - POS_PRINT("R "); - if ((f->tested & TEST_BAD_ERASE)) - POS_PRINT("E "); - if ((f->tested & TEST_BAD_WRITE)) - POS_PRINT("W "); + strcpy(tmpdev, f->name); + + tmpdev = strtok(tmpdev, delim); + msg_ginfo("%s", tmpdev); + curdevlen = strlen(tmpdev); + while ((tmpdev = strtok(NULL, delim)) != NULL) { + msg_ginfo("%s", delim); + curdevlen++; + tmpdevlen = strlen(tmpdev); + if (tmpdevlen >= mintoklen) + break; /* big enough to be on its own line */ + msg_ginfo("%s", tmpdev); + curdevlen += tmpdevlen; }
- while (pos < okcol + 18) { + for (i = curdevlen; i < maxchiplen; i++) msg_ginfo(" "); - pos++; - } - msg_ginfo("%d", f->total_size); - for (i = 0; i < 10 - digits(f->total_size); i++) + + if ((f->tested & TEST_OK_PROBE)) + msg_ginfo("P"); + else + msg_ginfo(" "); + if ((f->tested & TEST_OK_READ)) + msg_ginfo("R"); + else + msg_ginfo(" "); + if ((f->tested & TEST_OK_ERASE)) + msg_ginfo("E"); + else + msg_ginfo(" "); + if ((f->tested & TEST_OK_WRITE)) + msg_ginfo("W"); + else + msg_ginfo(" "); + for (i = 0; i < border; i++) + msg_ginfo(" "); + + if ((f->tested & TEST_BAD_PROBE)) + msg_ginfo("P"); + else + msg_ginfo(" "); + if ((f->tested & TEST_BAD_READ)) + msg_ginfo("R"); + else + msg_ginfo(" "); + if ((f->tested & TEST_BAD_ERASE)) + msg_ginfo("E"); + else + msg_ginfo(" "); + if ((f->tested & TEST_BAD_WRITE)) + msg_ginfo("W"); + else + msg_ginfo(" "); + for (i = 0; i < border + 1; i++) + msg_ginfo(" "); + + msg_ginfo("%5d", f->total_size); + for (i = 0; i < border; i++) msg_ginfo(" ");
s = flashbuses_to_text(f->bustype); - msg_ginfo("%s\n", s); + msg_ginfo("%s", s); + for (i = strlen(s); i < maxtypelen; i++) + msg_ginfo(" "); free(s); + + if (f->voltage.min == 0 && f->voltage.max == 0) + msg_gdbg("no info"); + else + msg_gdbg("%0.02f;%0.02f", + f->voltage.min/(double)1000, + f->voltage.max/(double)1000); + + /* print surplus vendor and device name tokens */ + while (tmpven != NULL || tmpdev != NULL) { + msg_ginfo("\n"); + if (tmpven != NULL){ + msg_ginfo("%s", tmpven); + curvenlen = strlen(tmpven); + while ((tmpven = strtok(NULL, delim)) != NULL) { + msg_ginfo("%s", delim); + curvenlen++; + tmpvenlen = strlen(tmpven); + /* big enough to be on its own line */ + if (tmpvenlen >= mintoklen) + break; + msg_ginfo("%s", tmpven); + curvenlen += tmpvenlen; + } + } else + curvenlen = 0; + + for (i = curvenlen; i < maxvendorlen; i++) + msg_ginfo(" "); + + if (tmpdev != NULL){ + msg_ginfo("%s", tmpdev); + curdevlen = strlen(tmpdev); + while ((tmpdev = strtok(NULL, delim)) != NULL) { + msg_ginfo("%s", delim); + curdevlen++; + tmpdevlen = strlen(tmpdev); + /* big enough to be on its own line */ + if (tmpdevlen >= mintoklen) + break; + msg_ginfo("%s", tmpdev); + curdevlen += tmpdevlen; + } + } + } + msg_ginfo("\n"); } }