/* для целей отладки */
struct flagtab {
int val; /* Целое значение флага */
const char *name; /* Строковое имя */
};
Эту структуру можно использовать для представления любого набора флагов с соответствующими строковыми значениями. Каждая отдельная группа флагов имеет соответствующую функцию, которая возвращает печатное представление флагов, которые установлены в настоящее время. Из eval.c
/* flags2str --- делает значения флагов удобочитаемыми */
const char *flags2str(int flagval) {
static const struct flagtab values[] = {
{ MALLOC, "MALLOC" },
{ TEMP, "TEMP" },
{ PERM, "PERM" },
{ STRING, "STRING" },
{ STRCUR, "STRCUR" },
{ NUMCUR, "NUMCUR" },
{ NUMBER, "NUMBER" },
{ MAYBE_NUM, "MAYBE_NUM" },
{ ARRAYMAXED, "ARRAYMAXED" },
{ FUNC, "FUNC" },
{ FIELD, "FIELD" },
{ INTLSTR, "INTLSTR" },
{ 0, NULL },
};
return genflags2str(flagval, values);
}
flags2str()
genflags2str() («общий флаг в строку»). getflags2str() является процедурой общего назначения, которая преобразует значение флага в строку. Из eval.c:1 /* genflags2str --- общая процедура для преобразования значения флага в строковое представление */
2
3 const char *
4 genflags2str(int flagval, const struct flagtab *tab)
5 {
6 static char buffer(BUFSIZ];
7 char *sp;
8 int i, space_left, space_needed;
9
10 sp = buffer;
11 space_left = BUFSIZ;
12 for (i = 0; tab[i].name != NULL; i++) {
13 if ((flagval & tab[i].val) != 0) {
14 /*
15 * обратите внимание на уловку, нам нужны 1 или 0, чтобы
16 * определить, нужен ли нам символ '|'.
17 */
18 space_needed = (strlen(tab[i].name) + (sp != buffer));
19 if (space_left < space_needed)
20 fatal(_("buffer overflow in genflags2str"));
21
22 if (sp >= buffer) {
23 *sp++ = '|';
24 space_left--;
25 }
26 strcpy(sp, tab[i].name);
27 /* обратите внимание на расположение! */
28 space_left -= strlen(sp);
29 sp += strlen(sp);
30 }
31 }
32
33 return buffer;
34 }
(Номера строк приведены относительно начала функции, а не файла.) Как и в предыдущей версии, идея заключалась в заполнении статического буфера строковыми значениями, такими, как "MALLOC | PERM | STRING | MAYBE_NUM
Указатель sp
space_left отслеживает количество оставшегося места; это уберегает нас от переполнения буфера.Основную часть функции составляет цикл (строка 12), проходящий через массив значений флагов. Когда флаг найден (строка 13), код вычисляет, сколько места требуется строке (строка 18) и проверяет, осталось ли столько места (строки 19–20).
Тест 'sp ! = buffer
|'. Добавляя результат (1 или 0) к длине строки, мы получаем правильное значение space_needed. Тот же тест с той же целью проводится в строке 22 для проверки строк 23 и 24, которые вставляют символ '|'.В заключение строки 26–29 копируют значение строки, выверяют количество оставшегося места и обновляют указатель sp