Чтение онлайн

на главную - закладки

Жанры

Linux программирование в примерах
Шрифт:

Этот код является повторяющимся и склонным к ошибкам, и для

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
отслеживает количество оставшегося места; это уберегает нас от переполнения буфера.

Основную часть функции составляет цикл (строка 12), проходящий через массив значений флагов. Когда флаг найден (строка 13), код вычисляет, сколько места требуется строке (строка 18) и проверяет, осталось ли столько места (строки 19–20).

Тест '

sp ! = buffer
' для первого значения флага завершается неудачей, возвращая 0. Для последующих флагов тест дает значение 1. Это говорит нам, что между значениями должен быть вставлен разделительный символ '
|
'. Добавляя результат (1 или 0) к длине строки, мы получаем правильное значение
space_needed
. Тот же тест с той же целью проводится в строке 22 для проверки строк 23 и 24, которые вставляют символ '
|
'.

В заключение строки 26–29 копируют значение строки, выверяют количество оставшегося места и обновляют указатель

sp
. Строка 33 возвращает адрес буфера, который содержит печатное представление строки.

Теперь несколько слов относительно статического буфера. Обычно хорошая практика программирования не одобряет использование функций, возвращающих адреса статических буферов: множественные вызовы таких функций каждый раз переписывают буфер, вынуждая вызывающего копировать возвращенные данные.

Более того, статический буфер по определению является буфером фиксированного размера. Что случилось с принципом GNU «никаких произвольных ограничений»?

Для ответа на эти вопросы нужно вспомнить, что это отладочная функция. Обычный код никогда не вызывает

getflags2str
; она вызывается лишь человеком, использующим отладчик. Ни у одного вызывающего нет указателя на буфер; как разработчику, осуществляющему отладку, нам нет дела до того, что буфер каждый раз переписывается при вызове функции.

Поделиться:
Популярные книги

Третий

INDIGO
Фантастика:
космическая фантастика
попаданцы
5.00
рейтинг книги
Третий

Имперец. Том 3

Романов Михаил Яковлевич
2. Имперец
Фантастика:
боевая фантастика
попаданцы
альтернативная история
7.43
рейтинг книги
Имперец. Том 3

Камень. Книга пятая

Минин Станислав
5. Камень
Фантастика:
боевая фантастика
6.43
рейтинг книги
Камень. Книга пятая

Адвокат империи

Карелин Сергей Витальевич
1. Адвокат империи
Фантастика:
городское фэнтези
попаданцы
фэнтези
5.75
рейтинг книги
Адвокат империи

Я уже граф. Книга VII

Дрейк Сириус
7. Дорогой барон!
Фантастика:
боевая фантастика
попаданцы
аниме
5.00
рейтинг книги
Я уже граф. Книга VII

Законы Рода. Том 12

Мельник Андрей
12. Граф Берестьев
Фантастика:
юмористическое фэнтези
аниме
фэнтези
5.00
рейтинг книги
Законы Рода. Том 12

Метатель

Тарасов Ник
1. Метатель
Фантастика:
боевая фантастика
попаданцы
рпг
фэнтези
фантастика: прочее
постапокалипсис
5.00
рейтинг книги
Метатель

Путь Скорби

Распопов Дмитрий Викторович
2. 30 сребреников
Фантастика:
попаданцы
альтернативная история
фэнтези
фантастика: прочее
5.00
рейтинг книги
Путь Скорби

На границе империй. Том 9. Часть 4

INDIGO
17. Фортуна дама переменчивая
Фантастика:
космическая фантастика
попаданцы
5.00
рейтинг книги
На границе империй. Том 9. Часть 4

Сильнейший Столп Империи. Книга 4

Ермоленков Алексей
4. Сильнейший Столп Империи
Фантастика:
фэнтези
аниме
фантастика: прочее
попаданцы
5.00
рейтинг книги
Сильнейший Столп Империи. Книга 4

Последний Паладин. Том 2

Саваровский Роман
2. Путь Паладина
Фантастика:
фэнтези
попаданцы
аниме
5.00
рейтинг книги
Последний Паладин. Том 2

Убивать чтобы жить 8

Бор Жорж
8. УЧЖ
Фантастика:
боевая фантастика
космическая фантастика
рпг
5.00
рейтинг книги
Убивать чтобы жить 8

На границе империй. Том 8

INDIGO
12. Фортуна дама переменчивая
Фантастика:
космическая фантастика
попаданцы
5.00
рейтинг книги
На границе империй. Том 8

Имперец. Том 5

Романов Михаил Яковлевич
4. Имперец
Фантастика:
попаданцы
альтернативная история
аниме
6.00
рейтинг книги
Имперец. Том 5