Очевидно, что когда Макропроцессор обрабатывает макровызов, он уже должен «знать» макроопределение данной макрокоманды. Для обеспечения этого таблицы макроопределений и имен макроопределений должны быть созданы до начала обработки макровызовов. Поэтому Макропроцессор должен состоять из двух проходов, на первом проходе строятся таблицы макроопределений и имен макроопределений, а на втором осуществляется обработка макровызовов. Если макроопределения сосредоточены в начале исходного модуля, то Макропроцессор может быть и однопроходным. Ниже мы приводим алгоритм работы 2-проходного Макропроцессора, при этом мы исходим из следующих предпосылок:
u наш Макропроцессор является независимым от Ассемблера;
u таблица параметров объединяется с таблицей локальных переменных, в дальнейшем мы называем объединенную таблицу таблицей локальных переменных;
u операторы Макроязыка включают в себя: MACRO, MEND, MEXIT, MNOTE, LOCL, GLBL, SET, MGO, MIF;
u обеспечиваются локальные и глобальные переменные макроопределений, уникальные метки.
Алгоритм выполнения 1-го прохода следующий:
F Блок1:1-й проход Макропроцессора
F Блок2:Инициализация: открытие исходного файла, создание пустых таблиц, признак «обработка макроопределения» устанавливается в FALSE.
F Блок3:Чтение следующей строки исходного файла с проверкой конца файла.
F Блок4:Если при чтении строки найден конец файла, выводится сообщение об ошибке, закрываются файлы, освобождается память...
F Блок5:...и Макропроцессор завершается с признаком ошибки.
F Блок6:Если конец файла не достигнут, выполняется лексический разбор прочитанной строки с выделением имени и мнемоники операции.
F Блок7:Алгоритм Макропроцессора разветвляется в зависимости от мнемоники операции
F Блок8:Если мнемоника операции MACRO — заголовок макроопределения, то в таблицу имен макроопределений заносится имя, находящееся в этом операторе и начальный адрес свободной области в таблице макроопределений. (При занесении имени в таблицу имен макроопределений проверяется, нет ли уже в таблице такого имени, если есть — ошибка)
F Блок9:Оператор MACRO записывается в таблицу макроопределений.
F Блок10:Признак «обработка макроопределения» устанавливается в TRUE.
F Блок11:Если мнемоника операции MEND — конец макроопределения, то оператор записывается в таблицу макроопределений...
F Блок12:...и признак «обработка макроопределения» устанавливается в FALSE.
F Блок13:Если мнемоника операции END — конец программы, то проверяется установка признака «обработка макроопределения».
F Блок14:Если этот признак установлен в TRUE, т.е., конец программы встретился до окончания макроопределения, то выводится сообщение об ошибке, закрываются файлы, освобождается память...
F Блок15:...и Макропроцессор завершается с признаком ошибки.
F Блок16:Если этот признак установлен в FALSE, то выполняются завершающие операции ...
F Блок17:...и заканчивается 1-й проход Макропроцессора.
F Блок18:При любой другой мнемонике оператора проверяется установка признака «обработка макроопределения».
F Блок19:Если этот признак установлен в TRUE, то оператор записывается в таблицу макроопределений, если признак установлен в FALSE, то оператор игнорируется Макропроцессором.
Алгоритм выполнения 2-го прохода следующий:
F Блок1:2-й проход макропроцессора
F Блок2:Начальные установки: открытие файлов, создание пустых таблиц. Признак режима обработки устанавливается в значение «обработка программы».
F Блок3:Признак конца обработки установлен?
F Блок4:Если признак конца обработки установлен, выполняются завершающие операции...
F Блок5:...и работа Макропроцессора заканчивается.
F Блок6:Выполняется разбор строки.
F Блок7:Проверяется признак режима обработки.
F Блок8:Если признак режима установлен в значение «обработка макроопределения», то проверяется мнемоника оператора.
F Блок9:Если в режиме обработки макроопределения встречается мнемоника MEND, то режим переключается в «обработка программы», все прочие операторы в режиме обработки макроопределения игнорируются.
F Блок10:Если признак режима работы установлен в значение «обработка программы», происходит ветвление алгоритма в зависимости от мнемоники оператора.
F Блок11:Обработка оператора MACRO заключается в установке режима обработки в значение «обработка программы».
F Блок12:Обработка директивы Ассемблера END заключается в установке признака окончания работы и выводе оператора в выходной файл.
F Блок13:Любая другая мнемоника ищется в Таблице машинных команд и в Таблице директив Ассемблера. Если мнемоника найдена в одной из этих таблиц, то...
F Блок14:...оператор просто выводится в выходной файл.
F Блок15:Если оператор не является оператором языка Ассемблера, то предполагается, что это макровызов и соответствующее мнемонике имя ищется в Таблице имен макроопределений.
F Блок16:Если имя не найдено в Таблице имен макроопределений, то оно ищется в библиотеках макроопределений.
F Блок17:Если имя не найдено и в библиотеках макроопределений, вырабатывается сообщение об ошибке и управление передается на чтение следующего оператора программы.
F Блок18:Если имя не найдено в библиотеках макроопределений, соответствующие элементы включаются в Таблицу имен макроопределений и в Таблицу макроопределений.
F Блок19:Если имя есть в Таблице макроопределений, выполняется обработка макровызова, после чего управление передается на чтение следующего оператора программы.
Алгоритм обработки макровызова следующий:
F Блок1:Обработка макровызова. На входе этого модуля есть номер элемента в Таблице имен макроопределений и разобранный текст оператора макровызова.
F Блок2:Создание пустых: Таблицы локальных переменных, Таблицы меток.
F Блок3:Чтение первой строки из Таблицы макроопределений по адресу, записанному в элементе Таблице имен макроопределений. (Здесь и далее мы подразумеваем, что после чтения очередной строки макроопределения указатель для следующего чтения устанавливается на адрес следующей строки, если он не изменен явным образом.)
F Блок4:Проверка параметров: сопоставление фактических параметров вызова с формальными параметрами, описанными в заголовке макроопределения (Заголовок находится в строке, только что считанной из Таблицы макроопределений).
F Блок5:При несоответствии фактических параметров формальным выдается сообщение об ошибке...
F Блок6:...и обработка макровызова завершается
F Блок7:При правильном задании фактических параметров параметры и их значения заносятся в Таблицу локальных переменных.
F Блок8:Создается и заполняется Таблица меток макроопределения. При этом текст макроопределения просматривается до оператора MEND, выявляются метки и заносятся в таблицу. Проверяется уникальность меток. После заполнения таблицы меток указатель чтения из Таблицы макроопределений устанавливается на вторую (следующую за заголовком строку) текста макроопределения.
F Блок9:Читается следующая строка текста макроопределения.
F Блок10:Если строка является комментарием Ассемблера, строка выводится в макрорасширение.
F Блок11:Если строка является комментарием Макроязыка, управление передается на чтение следующей строки макроопределения.
F Блок12:Выполняется разбор строки.
F Блок13:Алгоритм ветвится в зависимости от мнемоники оператора.
F Блок14:При обработке оператора LOCL имя локальной переменной ищется сначала в Таблице локальных переменных...
F Блок15:...а затем — в Таблице глобальных переменных.
F Блок16:Если имя найдено в одной из таблиц, формируется сообщение о неуникальном имени.
F Блок17:В противном случае заносится новая строка в таблицу локальных имен. В любом случае управление передается на чтение следующей строки макроопределения.
F Блок18:Обработка оператора GLBL отличается от оператора LOCL только тем, что новая строка создается в Таблице глобальных переменных.
F Блок19:При обработке оператора LOCL вычисляется выражение — операнд команды. Вычисление включает в себя подстановку значений входящих в выражение переменных. Возможны ошибки — из-за использования неопределенных имен и ошибок в синтаксисе выражения.
F Блок20:Имя переменной ищется сначала в Таблице локальных переменных.
F Блок21:Если имя найдено, изменяется его значение в Таблице локальных переменных.
F Блок22:Если имя переменной не найдено, оно ищется в Таблице глобальных переменных.
F Блок23:Если имя найдено в Таблице глобальных переменных, изменяется его значение в этой таблице.
F Блок24:Если имя не найдено ни в одной из таблиц, формируется сообщение о неопределенном имени.
F Блок25:При обработке оператора MIF вычисляется условное выражение — 1-й операнд команды (возможны ошибки).
F Блок26:Проверяется значение вычисленного условного выражения.
F Блок27:Если значение выражения «истина», имя метки — 2-го операнда команды ищется в Таблице меток макроопределения.
F Блок28:Если метка найдена в таблице, указатель для следующего чтения из Таблице макроопределений устанавливается на адрес соответствующий метке
F Блок29:Если метка найдена в таблице, выдается сообщение о неопределенной метке.
F Блок30:При обработке оператора MGO имя метки — операнда команды ищется в Таблице меток макроопределения.
F Блок31:Если метка найдена в таблице, указатель для следующего чтения из Таблице макроопределений устанавливается на адрес соответствующий метке.
F Блок32:Если метка найдена в таблице, выдается сообщение о неопределенной метке.
F Блок33:При обработке оператора MNOTE выводится сообщение, определяемое операндом.
F Блок34:Устанавливается и анализируется код серьезности. Код серьезности является общим для всей работы Макропроцессора, его значение изменяется только, если новое значение больше текущего (более серьезная ошибка)
F Блок35:Если код серьезности не допускает продолжения работы Макропроцессора, устанавливается признак завершения работы.
F Блок36:При обработке оператора MEXIT устанавливается и анализируется код серьезности.
F Блок37:Если код серьезности не допускает продолжения работы Макропроцессора, устанавливается признак завершения работы.
F Блок38:Освобождаются структуры данных, созданные для обработки макровызова...
F Блок39:...и обработка макровызова завершается.
F Блок40:При обработке оператора MEND освобождаются структуры данных, созданные для обработки макровызова...
F Блок41:...и обработка макровызова завершается.
F Блок42:Любая другая мнемоника операции означает, что оператор является не оператором Макроязыка, а оператором языка Ассемблера. В этом случае прежде всего проверяется, не имеет ли оператор метки, которая должна быть уникальной.
F Блок43:Если оператор имеет такую метку, формируется имя уникальной метки и индекс уникальных меток увеличивается на 1.
F Блок44:Выполняются подстановки в операторе языка Ассемблера (значение имен ищутся в Таблицах локальных и глобальных переменных, возможны ошибки).
F Блок45:Оператор языка Ассемблера записывается в макрорасширение.