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

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

Жанры

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

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

Газлайтер. Том 10

Володин Григорий
10. История Телепата
Фантастика:
боевая фантастика
5.00
рейтинг книги
Газлайтер. Том 10

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

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

Звездная Кровь. Изгой

Елисеев Алексей Станиславович
1. Звездная Кровь. Изгой
Фантастика:
боевая фантастика
попаданцы
рпг
5.00
рейтинг книги
Звездная Кровь. Изгой

Хозяин Теней 4

Петров Максим Николаевич
4. Безбожник
Фантастика:
попаданцы
аниме
фэнтези
5.00
рейтинг книги
Хозяин Теней 4

Картофельное счастье попаданки

Иконникова Ольга
Фантастика:
фэнтези
5.00
рейтинг книги
Картофельное счастье попаданки

Экзорцист: Проклятый металл. Жнец. Мор. Осквернитель

Корнев Павел Николаевич
Фантастика:
фэнтези
героическая фантастика
5.50
рейтинг книги
Экзорцист: Проклятый металл. Жнец. Мор. Осквернитель

Доктора вызывали? или Трудовые будни попаданки

Марей Соня
Фантастика:
юмористическая фантастика
попаданцы
5.00
рейтинг книги
Доктора вызывали? или Трудовые будни попаданки

Метатель

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

Моя на одну ночь

Тоцка Тала
Любовные романы:
современные любовные романы
короткие любовные романы
5.50
рейтинг книги
Моя на одну ночь

Чехов. Книга 2

Гоблин (MeXXanik)
2. Адвокат Чехов
Фантастика:
фэнтези
альтернативная история
аниме
5.00
рейтинг книги
Чехов. Книга 2

Хозяин Теней 2

Петров Максим Николаевич
2. Безбожник
Фантастика:
попаданцы
аниме
фэнтези
5.00
рейтинг книги
Хозяин Теней 2

Сумеречный стрелок 7

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

Жизнь под чужим солнцем

Михалкова Елена Ивановна
Детективы:
прочие детективы
9.10
рейтинг книги
Жизнь под чужим солнцем

Красноармеец

Поселягин Владимир Геннадьевич
1. Красноармеец
Фантастика:
боевая фантастика
попаданцы
4.60
рейтинг книги
Красноармеец