Построение матрицы переходов конечного автомата
Преимущества этого компактного представления станут очевидными сразу после описания того, как оно может применяться для создания матрицы переходов. Этот код содержится в файле fsminit.c.
Процедура fsminit принимает три параметра. Параметр fsm указывает матрицу переходов, которая должна быть инициализирована. Параметр ttab задает адрес компактного представления конечного автомата, а параметр nstates определяет число состояний в результирующем конечном автомате.
Процедура fsminit вначале выполняет инициализацию всей матрицы переходов, устанавливая в ней значения TINVALID. Затем она обрабатывает в цикле каждый элемент компактного представления и вводит информацию о переходе между состояниями, определяемом этим элементом, в матрицу переходов. И наконец, эта процедура снова обрабатывает в цикле матрицу переходов и изменяет все незаполненные переходы таким образом, чтобы они указывали на недействительный переход, находящийся в конце компактного представления.
Основная часть кода процедуры fsminit является несложной. Однако при вводе информации о переходах в процедуре fsminit необходимо проводить различия между явным переходом и его сокращенным обозначением. Чтобы понять этот код, напомним, что в компактном представлении символ TCANY обозначает все символы, которые не были указаны явно. Поэтому при обработке информации об отдельном переходе в процедуре fsminit выполняется проверка символа, вызывающего переход. Если в записи указан символ TCANY, процедура fsminit обрабатывает в цикле все возможные символы и добавляет переход к любому символу, который еще не был инициализирован. Если в записи указан любой символ, отличный от TCANY, процедура fsminit заполняет элемент матрицы перехода, соответствующий одному этому символу.
Конечный автомат для вывода в сокет
Конечный автомат, приведенный на рис. 26.4, определяет действия, выполняемые клиентом при получении каждого символа, который поступил от сервера. Отдельный и более простой конечный автомат описывает способ обработки в клиентской программе символов, поступающих с клавиатуры. Мы называем конечный автомат, связанный с вводом данных на клавиатуре, конечным автоматом вывода в сокет. На первый взгляд его название кажется необычным. Но, как показано на рис. 26.7, клиентское программное обеспечение организовано так, что такое имя становится вполне оправданным. Главный поток читает данные либо из сокета, либо с клавиатуры и вызывает процедуру конечного автомата для их обработки. Конечный автомат, обрабатывающий данные, которые поступают с клавиатуры, связан с выводом в сокет.
Конечный автомат для вывода в сокет показан на рис. 26.8. Вместо определения состояния для каждой операции, в этом конечном автомате предусмотрено применение только трех состояний. Большинство операций выполняется в одном переходе, который переводит клиентскую программу из состояния, представляющего локальную обработку, в состояние, которое представляет (обычное) взаимодействие с удаленной системой. Клиент передает основную часть символов данных на удаленный сервер. Однако этот проект позволяет пользователю на время выйти из соединения передачи данных и вступить во взаимодействие с локальной клиентской программой.
Работа конечного автомата для вывода в сокет начинается с состояния KSREM0TE, что заставляет клиента передавать каждый символ, введенный с клавиатуры, на удаленный сервер. При нажатии пользователем на клавиатуре клавиши выхода {Esc} клиент переходит в состояние KSLOCAL, в котором он ожидает новых нажатий клавиш. Большинство нажатий клавиш, которые следуют за нажатием клавиши {Esc}, не имеют для этого конечного автомата никакого смысла, но некоторые из них заставляют клиентскую программу выполнить определенные действия и вернуться в состояние KSREM0TE. Только одно из них, KCSCRIPT, заставляет клиентскую программу перейти в состояние KSCOLLECT, в котором она собирает символы имени файла, применяемого для ведения протокола.