Нам был нужен способ воспроизведения проблемы на своей машине разработки, система с неудачей находилась в стороне за девять часовых поясов, а интерактивный запуск GDB через Атлантический океан мучителен. Мы воспроизвели проблему, заставив optimal_bufsize()
проверять значение специальной переменной окружения AWKBUFSIZE
. Когда ее значение равно "exact"
, optimal_bufsize()
всегда возвращает размер файла, каким бы он ни был. Если значением AWKBUFSIZE
является какое-нибудь целое число, функция возвращает это число. В противном случае, функция возвращается к прежнему алгоритму. Это дает нам возможность запускать тесты, не требуя постоянной перекомпиляции gawk
. Например,
$ AWKBUFSIZE=42 make check
Это запускает тестовый набор gawk
с использованием размера буфера в 42 байта. (Тестовый набор проходит.) Вот модифицированная версия optimal_bufsize()
:
1 /* optimal_bufsize --- определение оптимального размера буфера */
2
3 /*
4 * В целях отладки усовершенствуйте это следующим образом:
5 *
6 * Всегда используйте stat для файла, буфер stat используется кодом
7 * более высокого уровня.
8 * if (AWKBUFSIZE == "exact")
9 * return the file size
10 * else if (AWKBUFSIZE == число)
11 * всегда возвращать это число
12 * else
13 * if размер < default_blocksize
14 * return размер
15 * else
16 * return default_blocksize
17 * end if
18 * end if
19 *
20 * Приходится повозиться, чтобы иметь дело с AWKBUFSIZE лишь
21 * однажды, при первом вызове этой процедуры, а не при каждом
22 * ее вызове. Производительность, знаете ли.
23 */
24
25 size_t
26 optimal_bufsize(fd, stb)
27 int fd;
28 struct stat *stb;
29 {
30 char *val;
31 static size_t env_val = 0;
32 static short first = TRUE;
33 static short exact = FALSE;
34
35 /* обнулить все члены, на случай, если ОС их не использует. */
36 memset(stb, '\0', sizeof(struct stat));
37
38 /* всегда использовать stat на случай, если stb используется кодом более высокого уровня */
39 if (fstat(fd, stb) == -1)
40 fatal("can't stat fd %d (%s)", fd, strerror(errno));
41
42 if (first) {
43 first = FALSE;
44
45 if ((val = getenv("AWKBUFSIZE")) != NULL) {
46 if (strcmp(val, "exact") == 0)
47 exact = TRUE;
48 else if (ISDIGIT(*val)) {
49 for (; *val && ISDIGIT(*val); val++)
50 env_val = (env_val * 10) + *val - '0';
51
52 return env_val;
53 }
54 }
55 } else if (!exact && env_val > 0)
56 return env_val;
57 /* else
58 обрабатывать дальше */
59
60 /*
61 * System V.n, n < 4, не имеет в структуре stat размера системного
62 * блока файла. Поэтому нам нужно осуществить разумную догадку.
63 * Мы используем BUFSIZ из stdio, поскольку именно это имелось
64 * в виду прежде всего.
65 */
66 #ifdef HAVE_ST_BLKSIZE
67 #define DEFBLKSIZE (stb->st_blksize > 0 ? stb->st_blksize : BUFSIZ)
68 #else
69 #define DEFBLKSIZE BUFSIZ
70 #endif
71
72 if (S_ISREG(stb->st_mode) /* обычный файл */