Re: [PATCH 0/7] minmax: reduce compilation time
From: Linus Torvalds
Date: Sat Jul 27 2024 - 00:14:45 EST
On Fri, 26 Jul 2024 at 21:13, Linus Torvalds
<torvalds@xxxxxxxxxxxxxxxxxxx> wrote:
>
> Anyway, I'm throwing this out in the hopes that somebody will use this
> to go "look, file XYZ generates a ridiculous X-megabyte line".
Oh, and by "throwing this out" I meant to actually include the updated
"longest-line.c".
And somebody sane can write it in two lines of perl instead.
Linus
#include <stdio.h>
#include <ctype.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/stat.h>
static void die(const char *reason)
{
fprintf(stderr, "Fatal: %s\n", reason);
exit(1);
}
static unsigned long find_line(const char *line, unsigned long len)
{
unsigned long res = 0;
do {
res++;
if (*line == '\n')
break;
line++;
} while (--len);
return res;
}
/*
* By this time, we know the line length, and it has been
* NUL-terminated. We can change it and use the underlying
* data if we find a preprocessor linemarker.
*/
void track_cpp_line_number(char *line, unsigned long len,
int *lineno, const char **filename)
{
unsigned long num;
char *end;
if (line[0] != '#')
return;
if (line[1] != ' ')
return;
line += 2;
len -= 2;
num = strtoul(line, &end, 10);
if (!num)
return;
if (end == line)
return;
len -= end - line;
line = end;
// Remove flag at the end
if (len > 2) {
if (line[len-2] == ' ' && isdigit(line[len-1])) {
line[len-2] = 0;
len -= 2;
}
}
// Remove spaces from end
while (len > 1 && line[len-1] == ' ')
line[--len] = 0;
// We're done with 'len' now, don't bother */
while (*line == ' ')
line++;
if (*line == '"') {
end = strchr(++line, '"');
if (end)
*end = 0;
}
while (!strncmp(line, "./", 2))
line += 2;
*lineno = num-1;
if (*line)
*filename = line;
}
int main(int argc, char **argv)
{
struct stat st;
char *buf;
unsigned long size;
long longest_len = 0;
char *longest_line = "";
int longest_lineno = 0;
const char *longest_file = "";
const char *file;
const char *unit;
int lineno = 0, fd;
fd = 0;
file = "stdin";
if (argc > 1) {
file = argv[1];
fd = open(file, O_RDONLY);
if (fd < 0) die("open");
}
if (fstat(fd, &st)) die("stat");
if (!S_ISREG(st.st_mode)) die("Not a regularfile");
size = st.st_size;
buf = malloc(size+1);
if (!buf) die("malloc failed");
if (read(fd, buf, size) != size) die("read failed");
for (lineno = 1; size; lineno++) {
unsigned long len;
char *line = buf;
/* Find the line, NUL-terminate it */
len = find_line(buf, size);
buf[len-1] = 0;
buf += len;
size -= len;
/* Track preprocessor info */
track_cpp_line_number(line, len-1, &lineno, &file);
if (len <= longest_len)
continue;
longest_len = len;
longest_line = line;
longest_file = file;
longest_lineno = lineno;
}
/* Limit printout of longest line arbitrarily */
if (longest_len > 104)
memcpy(longest_line + 100, "...", 4);
unit = " bytes";
if (longest_len > 10*1024) {
unit = "kB";
longest_len = (longest_len+512) / 1024;
}
printf("Longest line is %s:%d (%lu%s)\n",
longest_file,
longest_lineno,
longest_len, unit);
printf(" '%s'\n", longest_line);
return 0;
}