Linux программирование в примерах
Часть 172 из 253 Информация о книге
$ <b>ed -p '> ' sayings</b> /* Запуск ed, '> ' используется как приглашение */sayings: No such file or directory> <b>a</b> /* Добавить текст */Hello, worldDon't panic<b>^C</b> /* Сгенерировать SIGINT */? /* Сообщение об ошибке ''один размер подходит всем'' */> <b>1,$p</b> /* ed возвращается в командную строку */Hello, world /* '1,$p' prints all the lines */Don't panic> <b>w</b> /* Сохранить файл */25> <b>q</b> /* Все сделано */Внутри себя
устанавливает перед циклом команд точку возврата, и обработчик сигнала осуществляет нелокальный переход на эту точку возврата.ed12.5.1. Использование стандартных функций:
иsetjmp()longjmp()Нелокальные переходы осуществляются с помощью функций
иsetjmp(). Эти функции используются в двух разновидностях. Традиционные процедуры определены стандартом ISO С:longjmp()#include <setjmp.h> /* ISO С */int setjmp(jmp_buf env);void longjmp(jmp_buf env, int val);Тип
определен черезjmp_bufвtypedef.<setjmp.h>сохраняет текущее «окружение» вsetjmp().envобычно является глобальной или статической на уровне файла переменной, так что она может использоваться из вызванной функции. Это окружение включает любую информацию, необходимую для перехода на местоположение, из которого была вызванаenv. Содержаниеsetjmp()по своей природе машинно-зависимо; таким образом,jmp_bufявляется непрозрачным типом: тем, что вы используете, не зная, что находится внутри него.jmp_bufвозвращает 0, когда она вызывается для сохранения вsetjmp()текущего окружения. Ненулевое значение возвращается, когда с использованием окружения осуществляется нелокальный переход:jmp_bufjmp_buf command_loop; /* На глобальном уровне *//* ... затем в main() ... */if (setjmp(command_loop) == 0) /* Состояние сохранено, продолжить */;else /* Мы попадаем сюда через нелокальный переход */printf("?\n"); /* ed's famous message *//* ... теперь начать цикл команд ... */осуществляет переход. Первым параметром являетсяlongjmp(), который должен быть инициализирован с помощьюjmp_buf. Второй является целым ненулевым значением, котороеsetjmp()возвращает в первоначальное окружение. Это сделано так, что код, подобный только что показанному, может различить установку окружения и прибытие путем нелокального перехода.setjmp()Стандарт С утверждает, что даже если
вызывается со вторым аргументом, равным 0,longjmp()по-прежнему возвращает ненулевое значение. В таком случае она возвращает 1.setjmp()Возможность передать целое значение и вернуться обратно из
полезна; это позволяет коду уровня пользователя различать причину перехода. Например,setjmp()использует эту возможность для обработки операторовgawkиbreakвнутри циклов. (Язык awk осознанно сделан похожим на С в своем синтаксисе для циклов, с использованиемcontinue,while,do-while,forиbreak.) Использованиеcontinueвыглядит следующим образом (изsetjmp()в дистрибутивеeval.c3.1.3):gawk507 case Node_K_while:508 PUSH_BINDING(loop_tag_stack, loop_tag, loop_tag_valid);509510 stable_tree = tree;511 while (eval_condition(stable_tree->lnode)) {512 INCREMENT(stable_tree->exec_count);513 switch (setjmp(loop_tag)) {514 case 0: /* обычный не переход */515 (void)interpret(stable_tree->rnode);516 break;517 case TAG_CONTINUE: /* оператор continue */518 break;519 case TAG_BREAK: /* оператор break */520 RESTORE_BINDING(loop_tag_stack, loop_tag, loop_tag_valid);521 return 1;522 default:523 cant_happen();524 }525 }526 RESTORE_BINDING(loop_tag_stack, loop_tag, loop_tag_valid);527 break;Этот фрагмент кода представляет цикл
. Строка 508 управляет вложенными циклами посредством стека сохраненных переменныхwhile. Строки 511–524 выполняют циклjmp_buf(используя цикл Сwhile!). Строка 511 проверяет условие цикла. Если оно истинно, строка 513 выполняетwhileна возвращаемое значениеswitch. Если оно равно 0 (строки 514–516), строка 515 выполняет тело оператора. Однако, когдаsetjmp()возвращаетsetjmp()илиTAG_BREAK, операторTAG_CONTINUEобрабатывает их соответствующим образом (строки 517–518 и 519–521 соответственно).switch