[Содержание]   [Назад]   [Пред]   [Вверх]   [След]   [Вперед]  


10. Интерфейс командной строки

Все кнопки, на которые вы щелкаете в DDD, в результате переводятся в команды отладчика; они показываются в консоли отладчика. Вы также можете набирать и редактировать эти команды непосредственно.

10.1 Ввод команд

Вы можете общаться с командным интерфейсом подчиненного отладчика в консоли отладчика. Вводите команды в подсказке -- это `(gdb)' для GDB, `(dbx)' для DBX, `(ladebug)' для Ladebug, `>' для XDB, `>' и `нить[глубина]' для JDB, или `(Pydb)' для PYDB, или `DB<>' для Perl. Вы можете использовать любые команды отладчика; для ввода набирайте клавишу Return.

10.1.1 Завершение команд

При использовании GDB или Perl вы можете завершать команды и аргументы, нажимая TAB. Это работает в консоли отладчика, а также во всех остальных текстовых окнах.

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

Нажимайте клавишу TAB всякий раз, когда вы хотите, чтобы GDB дополнил остаток слова. Если есть только один вариант, GDB дополняет слово и ждет, пока вы завершите команду (или нажмете RET для ее ввода). Например, если вы наберете

(gdb) info bre TAB

GDB дополнит остаток слова `breakpoints', поскольку это единственная подкоманда info, начинающаяся на `bre':

(gdb) info breakpoints

Теперь вы можете либо нажать RET, чтобы запустить команду info breakpoints, либо нажать забой и ввести что-то еще, если `breakpoints' -- это не та команда, которую вы собирались ввести. (Если бы вы были точно уверены, что хотите info breakpoints, вы могли бы просто набрать RET сразу после `info bre', применив возможность сокращения команд, а не дополнение.)

Если есть несколько вариантов следующего слова, то когда вы нажимаете TAB, DDD издает звуковой сигнал. Вы можете либо набрать больше знаков и попробовать снова, либо просто нажать TAB второй раз; GDB покажет все варианты завершения этого слова. Например, вы можете захотеть установить точку останова на подпрограмме, чье имя начинается на `make_', но когда вы набираете b make_TAB, DDD просто пищит. Если вы снова нажмете TAB, будут показаны имена всех функций из вашей программы, которые так начинаются. Если вы еще раз нажмете TAB, вы будете проходить по списку завершений, например:

(gdb) b make_ TAB

DDD выдает сигнал; снова нажмите TAB и увидите вот это:

make_a_section_from_file     make_environ               
make_abs_section             make_function_type         
make_blockvector             make_pointer_type          
make_cleanup                 make_reference_type        
make_command                 make_symbol_completion_list
(gdb) b make_ TAB

DDD предоставляет одно дополнение за другим:

(gdb) b make_a_section_from_file TAB
(gdb) b make_abs_section TAB
(gdb) b make_blockvector TAB

Показав возможные варианты, GDB копирует незавершенный ввод (в этом примере `b make_'), чтобы вы могли закончить команду -- повторно нажав TAB или введя остаток вручную.

Иногда вам нужна такая строка, которая хотя логически и является "словом", но содержит скобки или другие знаки, которые GDB обычно не включает в свое понятие слова. Чтобы завершение слов работало в таких случаях, вы можете заключать слова в командах GDB в одиночные кавычки (').

Наиболее вероятна ситуация, когда вам это понадобилось для набора имени функции Си++. Это так, потому что Си++ допускает перезагрузку функций (разные определения одной функции, отличающиеся типом аргумента). Например, когда вы хотите поставить точку останова, вам может понадобиться указать, имеете ли вы в виду версию name, принимающую параметр int, name(int), или же версию, принимающую параметр float, name(float). Чтобы использовать завершение слов в этой ситуации, наберите в начале имени функции одиночную кавычку '. Это предупреждает GDB о том, что когда вы нажимаете TAB, чтобы запросить завершение слова, ему следует принять во внимание больше информации, чем обычно:

(gdb) b 'bubble( TAB
bubble(double,double)    bubble(int,int)
(gdb) b 'bubble(

В некоторых случаях DDD может понять, что для завершения имени требуется поставить кавычки. Когда это происходит, DDD вставляет кавычку за вас (завершая в то же время насколько может), если вы сначала не набрали ее:

(gdb) b bub TAB

DDD изменяет введенную вами строку на показанную ниже и
выдает звуковой сигнал:

(gdb) b 'bubble(

Вообще, DDD может понять, когда нужна кавычка (и вставляет ее), если в момент запроса завершения перезагруженного символа вы еще не начали набирать список аргументов.

Если вы предпочитаете использовать клавишу TAB для переключения между объектами, снимите установку `Edit => Preferences => General => TAB Key completes in All Windows'. Это полезно в том случае, если фокус клавиатуры управляется указателем мыши (смотрите ниже), а у клавиши TAB нет особого назначения. Если эта установка включена, клавиша TAB завершает только в консоли отладчика.

Данная установка привязана к такому ресурсу:

Ресурс: globalTabCompletion (класс GlobalTabCompletion)
Если это `on' (по умолчанию), клавиша TAB завершает аргументы во всех окнах. Если это `off', TAB завершает аргументы только в консоли отладчика.

10.1.2 История команд

Вы можете повторить предыдущие и последующие команды, нажимая стрелки Up и Down, соответственно. Это подставляет более ранние или более поздние команды в командную строку; чтобы применить текущую команду, нажмите Return.

Если вы введете пустую строку (просто нажмете Return в подсказке отладчика), будет повторена последняя команда.

`Commands => Command History' показывает историю команд.

PICS/ddd-history

Вы можете запустить поиск предыдущих команд, нажав Ctrl+B. Это вызывает режим наращиваемого поиска, где вы можете ввести строку, которую следует искать в предыдущих командах. Чтобы повторить поиск, нажмите Ctrl+B еще раз, а для поиска в обратном направлении используйте Ctrl+F. Чтобы вернуться в обычный режим, нажмите ESC или наберите любую команду управления курсором.

История команд автоматически сохраняется при выходе из DDD. Вы можете выключить эту возможность, установив следующий ресурс в значение `off':

Ресурс: saveHistoryOnExit (класс SaveHistoryOnExit)
Если это `on' (по умолчанию), история команд автоматически сохраняется при выходе из DDD.

10.2 Ввод команд с терминала

Вместо того чтобы вводить команды с консоли отладчика, вы, возможно, предпочтете набирать их в окне терминала, из которого был вызван DDD.

Когда DDD вызывается с ключом --tty, он включает TTY-интерфейс, принимая команды отладчика со стандартного ввода и пересылая вывод отладчика на стандартный вывод, как если бы подчиненный отладчик был вызван непосредственно. В остальном все функциональные возможности DDD остаются такими же.

По умолчанию, если DDD был вызван с ключом --tty, консоль отладчика закрыта. Чтобы открыть ее, используйте `View => Debugger Console'.

DDD можно настроить на использование библиотеки `readline' для чтения команд со стандартного ввода. Эта библиотека GNU предоставляет единый пользовательский интерфейс для программ, управляемых из командной строки. Ее преимущества: редактирование команд "на месте" в стиле GNU Emacs или vi, подстановка из истории, как в csh, и сохраняемая между сеансами отладки история команд. См. раздел `Command Line Editing' в Debugging with GDB, для получения дополнительной информации о редактировании командой строки через TTY-интерфейс.

10.3 Интегрирование DDD

Вы можете запускать DDD как подчиненный отладчик в других интерфейсах для отладчиков, комбинируя их возможности с возможностями DDD.

Чтобы запустить DDD в качестве подчиненного отладчика в другой интерфейсной программе, нужно настроить ее так, чтобы вместо ее подчиненного отладчика работал бы `ddd --tty'. Когда DDD вызывается с ключом --tty, он включает TTY-интерфейс, принимая команды отладчика со стандартного ввода и пересылая вывод отладчика на стандартный вывод, как если бы подчиненный отладчик был вызван непосредственно. В остальном поведение DDD не меняется.

В том случае, если ваш интерфейс отладчика использует ключ GDB -fullname, чтобы GDB сообщал позиции исходного кода, --tty задавать не обязательно. DDD распознает ключ -fullname, понимает, что его вызвали из другой интерфейсной программы, и автоматически задействует TTY-интерфейс.

Если запустить DDD с ключом -fullname, консоль отладчика и окно исходного кода изначально выключены, так как предполагается, что их предоставит внешний интерфейс. Если же нужно, вы можете зайти в меню `View' и включить эти окна.

10.3.1 Использование DDD с Emacs

Чтобы интегрировать DDD с Emacs, наберите в Emacs M-x gdb или M-x dbx, чтобы запустить сеанс отладки. В подсказке введите ddd --tty (и потом --dbx или --gdb, если нужно) и имя отлаживаемой программы. Далее действуйте как обычно.

10.3.2 Использование DDD с XEmacs

Чтобы интегрировать DDD с XEmacs, установите переменную gdb-command-name равной `"ddd"', вставив в свой файл `~/.emacs' следующую строку:

(setq gdb-command-name "ddd")

Кроме того, можно вычислить это выражение, нажав ESC : и введя его непосредственно (ESC ESC в XEmacs 19.13 и более ранних).

Чтобы запустить из XEmacs сеанс отладки DDD, используйте `M-x gdb' или `M-x gdbsrc'. Далее работайте как обычно.

10.3.3 Использование DDD с @acronym{XXGDB}

Чтобы интегрировать DDD с @acronym{XXGDB}, вызовите xxgdb так:

xxgdb -db_name ddd -db_prompt '(gdb) '

10.4 Определение кнопок

Для упрощения взаимодействия с DDD вы можете добавлять свои собственные командные кнопки. Можно добавлять кнопки внизу консоли отладчика (`Кнопки консоли'), окна исходного кода (`Кнопки исходника') или окна данных (`Кнопки данных').

Для определения отдельных кнопок служит редактор кнопок, вызываемый через `Commands => Edit Buttons'. Редактор кнопок показывает текст, где каждая строка содержит команду для одной кнопки. Щелчок на `OK' создает соответствующие этому тексту кнопки. Если текст пуст (по умолчанию), кнопки не создаются.

В качестве простого примера, предположим, что вы хотите создать кнопку `print i'. Вызовите `Commands => Edit Buttons' и введите в редакторе кнопок строку `print i'. Затем щелкните на `OK'. Тогда внизу консоли отладчика появится кнопка с именем `Print i' -- попробуйте применить ее! Чтобы удалить эту кнопку, снова откройте редактор кнопок, очистите строку `print i' и нажмите `OK'.

Если команда кнопки содержит `()', строка `()' будет автоматически заменяться на содержимое поля аргумента. К примеру, кнопка с именем `return ()' будет выполнять команду GDB `return', передавая ей текущее содержимое поля аргумента.

По умолчанию DDD выключает все кнопки, чьи команду не поддерживаются подчиненным отладчиком. Чтобы задействовать их, снимите переключатель `Enable supported buttons only' в редакторе кнопок.

PICS/ddd-button-editor

Кроме того, DDD позволяет задавать для определяемых пользователем кнопок управляющие последовательности и метки. См. раздел 10.4.1 Настройка кнопок, для получения подробностей.

10.4.1 Настройка кнопок

DDD позволяет определять дополнительные командные кнопки; См. раздел 10.4 Определение кнопок. Данный раздел описывает ресурсы, контролирующие определяемые пользователем кнопки.

Ресурс: consoleButtons (класс Buttons)
Разделяемый переводами строки список кнопок, которые следует добавить внизу консоли отладчика. Каждая кнопка отдает команду, определяемую ее именем.

Следующие знаки имеют специальное значение:

  • Команды, завершающиеся на ..., вставляют в консоль отладчика свое имя и пробел.
  • Команды, завершающиеся на управляющий знак (то есть `^', после которого стоит буква или `?'), вставляют указанный управляющий знак.
  • Строка `()' заменяется на текущее содержимое поля аргумента.
  • Строка, заданная ресурсом `labelDelimiter' (обычно `//') разделяет имя команды и метку кнопки. Если метка не указана, вместо нее используется имя команды с первой заглавной буквой.

Следующие имена кнопок зарезервированы:

`Apply'
Послать заданную команду отладчику.
`Back'
Искать ранее выбранную позицию в исходном коде.
`Clear'
Очистить текущую команду.
`Complete'
Завершить текущую команду.
`Edit'
Редактировать текущий исходный файл.
`Forward'
Искать следующую выбранную позицию в исходном коде.
`Make'
Вызвать программу `make', используя последние заданные ей аргументы.
`Next'
Показать следующую команду.
`No'
Ответить на текущую подсказку отладчика `no'. Эта кнопка видима, только если отладчик задает вопрос, на который можно ответить да/нет.
`Prev'
Показать предыдущую команду.
`Reload'
Перезагрузить исходный файл.
`Yes'
Ответить на текущую подсказку отладчика `yes'. Эта кнопка видима, только если отладчик задает вопрос, на который можно ответить да/нет.

По умолчанию значение этого ресурса пусто -- кнопки на консоли не создаются.

Вот несколько примеров, которые можно вставить в файл `~/.ddd/init'. Это установки DDD 1.x:

Ddd*consoleButtons: Yes\nNo\nbreak^C

Эта установка создает еще несколько кнопок:

  Ddd*consoleButtons: \
  Yes\nNo\nrun\nClear\nPrev\nNext\nApply\nbreak^C

Также смотрите ресурсы `dataButtons', `sourceButtons' и `toolButtons'.

Ресурс: dataButtons (класс Buttons)
Разделяемый переводами строки список кнопок, которые следует добавить внизу окна данных. Каждая кнопка отдает команду, задаваемую ее именем. Синтаксис подробно описан для ресурса `consoleButtons' выше.

По умолчанию значение этого ресурса пусто -- кнопки в окне данных не создаются.

Ресурс: sourceButtons (класс Buttons)
Разделяемый переводами строки список кнопок, которые следует добавить внизу окна исходного кода. Каждая кнопка отдает команду, задаваемую ее именем. Синтаксис подробно описан для ресурса `consoleButtons' выше.

По умолчанию значение этого ресурса пусто -- кнопки в окне исходного кода не создаются.

Вот несколько примеров, которые можно вставить в файл `~/.ddd/init'. Это установки DDD 1.x

Ddd*sourceButtons: \
  run\nstep\nnext\nstepi\nnexti\ncont\n\
  finish\nkill\nup\ndown\n\
  Back\nForward\nEdit\ninterrupt^C

Эта установка создает несколько кнопок, которых нет в панели команд:

  Ddd*sourceButtons: \
  print *()\ngraph display *()\nprint /x ()\n\
  whatis ()\nptype ()\nwatch ()\nuntil\nshell

Более профессиональная установка использует настраиваемые метки кнопок.

  Ddd*sourceButtons: \
  print *(()) // Print *()\n\
  graph display *(()) // Display *()\n\
  print /x ()\n\
  whatis () // What is ()\n\
  ptype ()\n\
  watch ()\n\
  until\n\
  shell

Смотрите также ресурсы `consoleButtons' и `dataButtons' выше и ресурс `toolButtons' ниже.

Ресурс: toolButtons (класс Buttons)
Разделяемый переводами строки список кнопок, которые следует добавить к панели команд или командной панели инструментов (см. раздел 3.3.1.1 Выключение панели команд). Каждая кнопка отдает команду, задаваемую ее именем. См. раздел 10.4 Определение кнопок, подробное описание синтаксиса кнопок.

По умолчанию значение этого ресурса равно

Ddd*toolButtons: \
run\nbreak^C\nstep\nstepi\nnext\nnexti\n\
until\nfinish\ncont\n\kill\n\
up\ndown\nBack\nForward\nEdit\nMake

Для каждой кнопки нужно указать положение на панели команд, используя ресурсы `XmForm'. Инструкции смотрите в файле ресурсов по умолчанию `Ddd'.

Если значение ресурса `toolButtons' пусто, панель команд не создается.

Следующие ресурсы определяют кнопки более подробно:

Ресурс: labelDelimiter (класс LabelDelimiter)
Строка, используемая для отделения меток от команд и клавиатурных эквивалентов. По умолчанию `//'.

Ресурс: verifyButtons (класс VerifyButtons)
Если `on' (по умолчанию), проверять каждую кнопку на предмет, действительно ли ее команда поддерживается подчиненным отладчиком. Если такая команда неизвестна, кнопка выключается. Если этот ресурс равен `off', проверка не производится: все команды принимаются "как есть".

10.5 Определение команд

Кроме команд для точек останова (см. раздел 5.1.8 Команды точек останова), DDD также позволяет вам определять свои команды. Определяемая пользователем команда -- это последовательность команд, которой вы присвоили собственное имя как отдельной команде. Эту новую команду можно вводить в подсказке отладчика или вызывать по кнопке.

10.5.1 Определение простых команд с использованием GDB

Кроме команд для точек останова (см. раздел 5.1.8 Команды точек останова), DDD также позволяет вам записывать последовательности команд в качестве новой, определенной пользователем команды GDB. Определяемая пользователем команда -- это последовательность команд GDB, которой вы придали новое имя как команде. В DDD для этой цели служит редактор команд, который вызывается через `Commands => Define Command'.

Команда GDB создается в пять шагов:

  1. Введите имя команды в поле `Command'. Используйте ниспадающий список справа, если хотите выбрать уже определенную команду.
  2. Щелкните на `Record', чтобы начать запись последовательности команд.
  3. Теперь отдавайте DDD команды. В процессе записи DDD не выполняет команды, а просто записывает их. Записанные команды показываются в консоли отладчика.
  4. Чтобы остановить запись, щелкните на `End' или введите в подсказке GDB слово `end'. Чтобы отменить запись, щелкните на `Interrupt' или нажмите ESC.
  5. Щелкните на `Edit >>', чтобы отредактировать записанные команды. Когда вы закончите с этим, щелкните на `Edit <<', и редактор команд закроется.

Когда команда определена, вы можете вводить ее в подсказке GDB. Кроме того, любую определенную пользователем команду можно применить, щелкнув на `Apply'.

Для удобства работы вы можете назначить для новой команды кнопку. Если включить одно из положений `Button', в указанном месте добавится кнопка с этой командой. Если вы хотите отредактировать эту кнопку, выберите `Commands => Edit Buttons'. См. раздел 10.4 Определение кнопок, обсуждение этой темы.

PICS/ddd-define-command

Когда выполняются определенные пользователем команды GDB, команды, составляющие ее определение, не печатаются. Ошибка в любой из команд последовательности приводит к останову выполнения.(33)

Команды, которые обычно запрашивают подтверждение, не задают вопросов при интерактивном использовании, если они находятся внутри определенной пользователем команды. Многие команды GDB, которые обычно печатают сообщения о том, что они делают в данный момент, не выводят этих сообщений при использовании из определенной пользователем команды.

Чтобы сохранить все определения команд, используйте `Edit => Save Options'.

10.5.2 Определение команд с аргументами с использованием GDB

Если вы хотите передать определяемой пользователем команде аргументы, вы можете включить переключатель `()' в редакторе команд. Это приводит к двум результатам:

  • Во время записи команд все ссылки на поле аргумента воспринимаются символьно, а не буквально. Значение поля аргумента фиксировано и равно `$arg0', так GDB обозначает аргумент определяемой пользователем команды. Когда GDB будет выполнять эту команду, он заменит `$arg0' на текущий аргумент команды.
  • Когда команде придается кнопка, после команды дописывается текущее содержимое поля аргумента.

В процессе определения команды вы можете как угодно переключать кнопку `()', переходя от символьной подстановки поля аргумента к буквальной.

В качестве примера давайте определим команду contuntil, она будет устанавливать точку останова по заданному аргументу и продолжать выполнение.

  1. Введите в поле `Command' слово `contuntil'.
  2. Включите переключатель `()'.
  3. Теперь щелкните на `Record', и начнется запись. Заметьте, что содержимое поля аргумента сменилось на `$arg0'.
  4. Щелкните на `Break at ()', чтобы создать точку останова. Обратите внимание, записанная команда ссылается на `$arg0'.
  5. Щелкните на `Cont', чтобы продолжить выполнение.
  6. Завершите запись, щелкнув на `End'. Заметьте, что поле аргумента восстановило свое первоначальное значение.
  7. Наконец, щелкните на одном из положений `Button'. Это создает кнопку `Contuntil ()', где `()' будет заменяться на текущее содержимое поля аргумента -- и, таким образом, передаваться команде `contuntil'.
  8. Теперь вы можете использовать кнопку `Contuntil ()' или вводить команду `contuntil' в подсказке GDB. (Если вы планируете использовать ее часто, вы, возможно, захотите определить команду `cu', которая вызывает `contuntil' со своим аргументом. Это хорошее упражнение.)

У команд с аргументами есть маленький недостаток: у определяемой пользователем команды GDB нет никакой возможности получить доступ ко всему списку аргументов целиком; обрабатывается только первый аргумент (до пропуска). В будущих выпусках GDB это может измениться.

10.5.3 Определение команд с использованием других отладчиков

Если ваш подчиненный отладчик позволяет определять свои собственные последовательности команд, вы также можете использовать эти пользовательские команды из DDD; просто вводите их в подсказке отладчика.

Однако, вы можете столкнуться с некоторыми проблемами:

  • DDD не знает, что делает пользовательская команда, в отличие от хорошо документированных команд отладчика. Это может привести к несогласованности между DDD и подчиненным отладчиком. К примеру, если ваша пользовательская команда `bp' устанавливает точку останова, DDD может показать ее не сразу, поскольку он не знает, что `bp' изменяет состояние точек останова.
  • Вы не можете использовать команды DDD `graph' внутри пользовательской команды. Это естественно, так как пользовательские команды интерпретируются подчиненным отладчиком, а он не знает о командах DDD.

Для решения этих проблем DDD предоставляет простое средство, так называемые автокоманды. Если DDD получает от подчиненного отладчика какой-либо вывод вида `префикс команда', он интерпретирует команду, как если бы она была введена в подсказке отладчика. Префикс -- это определяемая пользователем строка, например `ddd: '.

Допустим, вы хотите определить команду gd, которая служит сокращением для graph display. Все, что должна сделать команда gd -- выдать строку

ddd: graph display аргумент

где аргумент -- это аргумент gd. При использовании GDB этого можно достичь с помощью команды echo. Вставьте в свой файл `~/.gdbinit' такие строки:

define gd
  echo ddd: graph display $arg0\n
end

Чтобы закончить подготовку, вы должны также установить ресурс `autoCommandPrefix' в значение префикса, который вы написали в команде, `ddd: '. Напишите в файле `~/.ddd/init':

Ddd*autoCommandPrefix: ddd:\ 

(Не забудьте поставить после обратной косой черты пробел.)

Теперь ввод gd foo в подсказке отладчика будет иметь тот же эффект, что и graph display foo.

Пожалуйста, обратите внимание: Для своих команд вам лучше выбрать какой-нибудь другой префикс, не `ddd: '. Это нужно делать, потому что автокоманды создают проблему с защитой, ведь выполнять можно любые команды. Только представьте себе, что некая злобная программа пишет во время отладки строку вроде `префикс shell rm -fr ~'! Поэтому обязательно придумайте свой собственный префикс; его длина должна быть не меньше трех знаков.


[Содержание]   [Назад]   [Пред]   [Вверх]   [След]   [Вперед]  

Наш баннер
Вы можете установить наш баннер на своем сайте или блоге, скопировав этот код:
RSS новости