Linux программирование в примерах
Шрифт:
Сначала мы покажем вам, как мы это делали первоначально. Вот (сокращенная версия)
flags2str
из ранней версии gawk
(3.0.6): 1 /* flags2str --- делает значения флагов удобочитаемыми */
2
3 char *
4 flags2str(flagval)
5 int flagval;
6 {
7 static char buffer[BUFSIZ];
8 char *sp;
9
10 sp = buffer;
11
12 if (flagval & MALLOC) {
13 strcpy(sp, "MALLOC");
14 sp += strlen(sp);
15 }
16 if (flagval & TEMP) {
17 if (sp >= buffer)
18 *sp++ = '|';
19 strcpy(sp, "TEMP");
20 sp += strlen(sp);
21 }
22 if (flagval & PERM) {
23 if (sp != buffer)
24 *sp++ = '|';
25 strcpy(sp, "PERM");
26 sp += strlen(sp);
27 }
/* ...многое то же самое, опущено для краткости... */
82
83 return buffer;
84 }
(Номера строк даны относительно начала функции.) Результатом является строка, что- то наподобие "
MALLOC | PERM | NUMBER
". Каждый флаг тестируется отдельно, и если он присутствует, действие каждый раз одно и то же: проверка того, что он не в начале буфера и что можно добавить символ '|
', скопировать строку на место и обновить указатель. Сходные функции существовали для форматирования и отображения других видов флагов в программе. Этот код является повторяющимся и склонным к ошибкам, и для
gawk
3.1 мы смогли упростить и обобщить его. Вот как gawk
делает это сейчас. Начиная с этого определения в awk.h
: /* для целей отладки */
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
определяет массив сопоставлений флагов со строками. По соглашению, значение флага 0 означает конец массива. Код вызывает для осуществления работы 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
отслеживает количество оставшегося места; это уберегает нас от переполнения буфера.
Поделиться:
Популярные книги
Зауряд-врач
1. Зауряд-врач
Фантастика:
альтернативная история
8.64
рейтинг книги
Адвокат империи
1. Адвокат империи
Фантастика:
городское фэнтези
попаданцы
фэнтези
5.75
рейтинг книги
Печать Пожирателя 3
3. Пожиратель
Фантастика:
городское фэнтези
аниме
сказочная фантастика
фэнтези
попаданцы
5.00
рейтинг книги
Вечный. Книга VII
7. Вечный
Фантастика:
боевая фантастика
рпг
попаданцы
5.00
рейтинг книги
Товарищ "Чума" 10
10. Товарищ "Чума"
Фантастика:
городское фэнтези
попаданцы
альтернативная история
5.00
рейтинг книги
Чайлдфри
Любовные романы:
современные любовные романы
6.51
рейтинг книги
Двойник Короля 6
6. Двойник Короля
Фантастика:
аниме
фэнтези
фантастика: прочее
попаданцы
5.00
рейтинг книги
Виктор Глухов агент Ада. Компиляция. Книги 1-15
Виктор Глухов агент Ада
Фантастика:
фэнтези
героическая фантастика
боевая фантастика
попаданцы
5.00
рейтинг книги
Шайтан Иван 4
4. Шайтан Иван
Фантастика:
попаданцы
альтернативная история
8.00
рейтинг книги
Бояръ-Аниме. Газлайтер. Том 30
30. История Телепата
Фантастика:
альтернативная история
аниме
фэнтези
5.00
рейтинг книги
Имперец. Том 1 и Том 2
1. Имперец
Фантастика:
попаданцы
альтернативная история
аниме
5.00
рейтинг книги
Хозяин Стужи 4
4. Злой Лед
Фантастика:
аниме
фэнтези
попаданцы
5.00
рейтинг книги
Бродяга 3
3. Бродяга
Фантастика:
фэнтези
попаданцы
5.00
рейтинг книги
Демон-хранитель
Фантастика:
фэнтези
мистика
5.20