Основную часть функции составляет цикл (строка 12), проходящий через массив значений флагов. Когда флаг найден (строка 13), код вычисляет, сколько места требуется строке (строка 18) и проверяет, осталось ли столько места (строки 19–20).
Тест '
sp ! = buffer
' для первого значения флага завершается неудачей, возвращая 0. Для последующих флагов тест дает значение 1. Это говорит нам, что между значениями должен быть вставлен разделительный символ '
|
'. Добавляя результат (1 или 0) к длине строки, мы получаем правильное значение
space_needed
.
Тот же тест с той же целью проводится в строке 22 для проверки строк 23 и 24, которые вставляют символ '
|
'.
В заключение строки 26–29 копируют значение строки, выверяют количество оставшегося места и обновляют указатель
sp
. Строка 33 возвращает адрес буфера, который содержит печатное представление строки.
Теперь несколько слов относительно статического буфера. Обычно хорошая практика программирования не одобряет использование функций, возвращающих адреса статических буферов: множественные вызовы таких функций каждый раз переписывают буфер, вынуждая вызывающего копировать возвращенные данные.
Более того, статический буфер по определению является буфером фиксированного размера. Что случилось с принципом GNU «никаких произвольных ограничений»?
Для ответа на эти вопросы нужно вспомнить, что это отладочная функция. Обычный код никогда не вызывает
getflags2str
; она вызывается лишь человеком, использующим отладчик. Ни у одного вызывающего нет указателя на буфер; как разработчику, осуществляющему отладку, нам нет дела до того, что буфер каждый раз переписывается при вызове функции.
На практике фиксированный размер также не является проблемой; мы знаем, что размер
BUFSIZ
достаточен для представления всех флагов, которые мы используем. Тем не менее, поскольку мы опытные и знаем, что вещи могут измениться, в
getflags2str
есть код, предохраняющий себя от переполнения буфера. (Переменная
space_left
и код в строках 18–20.)
В качестве отступления, использование
BUFSIZ
спорно. Эта константа должна использоваться исключительно для буферов ввода/вывода, но часто она используется также для общих строковых буферов. Такой код лучше убрать, определив явные константы, такие, как
FLAGVALSIZE
, и использовав в строке 11 '
sizeof (buffer)
'.
Вот сокращенный сеанс GDB, показывающий использование
flags2str
:
$ gdb gawk /* Запустить GDB с gawk */
GNU gdb 5.3
...
(gdb) break do_print /* Установить контрольную точку */
Breakpoint 1 at 0x805a584: file builtin.c, line 1547.
(gdb) run 'BEGIN { print "hello, world" }' /* Запустить программу */