В
Библиотеке Численного Анализа НИВЦ МГУ (www.srcc.msu.su/num_anal/) помещены описания библиотечных программ на языке ФОРТРАН. В
связи с переводом программ на язык Си, возникла необходимость сделать подобные
описания для языка Си, причем исходя из существующего описания на языке
ФОРТРАН. Документ, описывающий программу, состоит из нескольких разделов:
'Программа: <имя п/п>', 'Назначение',
'Математическое описание', 'Использование', 'Параметры'. 'Версии', 'Вызываемые
программы', 'Замечания по использованию', 'Пример использования', структуру и
особенности которых при переводе документации надо учитывать. Кроме этого
следует учесть, что документация предназначена для просмотра в Интернете и написана
с использованием тегов языка HTML. В результате этих
особенностей задача перевода документации включила в себя следующие основные
пункты:
- |
перевод
всех идентификаторов (кроме раздела 'Математическое описание') и имен всех
встречаемых программ на нижний регистр, причем задача усложняется тем, что
часть букв верхнего регистра, совпадающая по написанию с русскими, имеет
русскую кодировку; |
- |
добавление
к именам программ окончаний для имен версии Си: c_ ; например, имя AM01R заменяется на имя am01r_c ; |
- |
поиск
и замена в разделе 'Использование' первого оператора обращения к
программе на языке ФОРТРАН на оператор,
который ищется контекстным поиском и выделяется из текста программы на языке
Си; |
- |
поиск
и замена в разделе 'Пример использования' теста к программе на языке
ФОРТРАН на соответствующий тест на языке Си; при этом операторы теста в
разделе могут быть обрамлены произвольными пояснительными строками, которые
при поиске должны быть разграничены с тестом; |
- |
в
тексте может быть приведен вид первого оператора обращения к версии программы
или к подпрограмме, приложенной к тесту, на языке ФОРТРАН, который заменяется
на соответствующий оператор
языка Си, найденный в каталоге программ на Си; |
- |
операторы
и тесты программ на языке Си представлены в каталогах в виде заархивированных
zip-файлов, поэтому перед началом работы с файлом документации
все файлы надо разархивировать; |
- |
в силу
особенностей определенных разделов должен существовать механизм,
обеспечивающий контекстные преобразования только в указанном разделе или
группе разделов. |
Для
выполнения этой задачи создан сценарий, основные пункты которого описываются
ниже с приведением подробных комментариев:
1. Запись в первую ячейку общего
архива {{1}} тега <pre>
2. Запись во вторую ячейку общего
архива {{2}} тега </pre>
Цикл по основным каталогам поиска
(цикл охватывает пункты 3 – 22):
#ЦИКЛ:1?d:\docci\listcat.txt
Вся исходная
документация разбита на серию подкаталогов: am, pa, sf и др., определяющих отдельные
разделы документации. Имена подкаталогов соответствуют начальным символам имен
программ, находящимся в этом подкаталоге и содержат пять символов, последний из
которых определяет версию программы (например, AM02D, SF60R). Файл
цикла d:\docci\listcat.txt состоит
из строк с именами этих подкаталогов и участвует в организации цикла 1.
Соответствующие этим подкаталогам программы на языке Си находятся в
подкаталогах с именами am_c, pa_c, sf_c и др.,
а тесты - в подкаталогах с именами tam_c, tpa_c, tsf_c и др.
3.
Создание левого списка по файлам каталога цикла (например, из подкаталога am) c
расширением .htm
4.
Добавление в левый список файлов из подкаталога Библиотеки d:\num_anal\lib_na\cat\&1 _c\ (например, из подкаталога am_c). В
этом подкаталоге находятся zip-файлы
программ на Си из раздела, имя которого формируется после подстановки первой
лексемы &1 текущей
строки файла d:\docci\listcat.txt,
организующего цикл 1.
5.
Добавление в левый список файлов из подкаталога Библиотеки d:\num_anal\lib_na\cat\t&1 _c\ ( например, из подкаталога tam_c ). В
этом подкаталоге находятся zip-файлы
тестов на Си из раздела, имя которого формируется после подстановки первой
лексемы &1 из текущей
строки файла d:\docci\listcat.txt,
организующем цикл 1.
6.
Создание рабочего каталога files_&1 . В этот каталог в дальнейшем
соберем все распакованные файлы, которые будут использоваться для перекодировки
соответствующего раздела документации.
7.
Перепись файлов левого списка в каталог files_&1 .
8.
Создание правого списка zip-файлов
из каталога files_&1 ( например, files_am ) и запись этого списка в файл d:\docci\tmp\listzip.txt. Этот файл будет использован для организации внутреннего цикла
распаковки zip-файлов.
9. Цикл распаковки zip-файлов
через запуск внешнего процесса:
#ЦИКЛ:2?d:\docci\tmp\listzip.txt
Завершение
цикла 2:
#КОНЕЦ:2
10.
Удаление zip-файлов правого списка из каталога files_&1 после распаковки.
11.Создание
правого списка htm-файлов из каталога files_&1 и запись списка в файл d:\docci\tmp\listhtm_&1
.txt (например, создали файл listhtm_am.txt,
содержащий файлы Am00r.htm, Am01r.htm и др.).
12. Редактирование файла listhtm_&1 .txt,
используя таблицу контекстов:
Контекст поиска: |
Контекст замены: |
Комментарий: |
{?*~[.]}{.htm} |
#[{1} & {2} & "
" & {1} & "_c.c t" & {1} & "_c.c"//{0}] |
Формирование строк вида (f - имя файла): f.htm f_c.c
tf_c.c |
Цикл 3 по созданному на
предыдущем этапе файлу (цикл охватывает пункты 13 – 18):
#ЦИКЛ:3?d:\docci\tmp\listhtm_&1|1 .txt
13.
Запись в третью ячейку общего архива {{3}} обращения к п/п
с параметрами на Си из файла d:\docci\files_&1|1 \&2 . Здесь
каталог определяется первой лексемой файла цикла 1, а имя файла - второй
лексемой текущего цикла 3. Это действие выполняет контекстное преобразование:
Контекст поиска: |
Контекст замены: |
Комментарий: |
%%{&1|1 ???_c(}|{&1|1
????_c(} |
|
Начало блока: имя п/п,
начинающееся с имени каталога, плюс 3 или 4 произвольных символа (дополнение
до 5 символов исходного имени) плюс стандартное окончание имени _c. |
$${%@{} |
|
Конец блока: { в начале строки. |
%$ |
#[BlockOper(save,{10}, {{3}},1..-2)] |
Запись блока без
последней строки { в третью ячейку архива. |
14.
Запись в четвертую ячейку архива {{4}} теста на языке Си из файла d:\docci\files_&1|1
\&3 . Здесь каталог определяется первой лексемой файла цикла 1, а имя
теста - третьей лексемой текущего цикла 3. Это действие выполняет контекстное
преобразование:
Контекст поиска: |
Контекст замены: |
Комментарий: |
%%{main(void)} |
|
Начало блока: заданный
контекст. |
$$$ |
|
Конец блока: конец файла. |
%$ |
#[BlockOper(save,{10}, {{4}},1..-1)] |
Запись блока в четвертую
ячейку архива. |
15.
Изменение прописных букв на строчные в именах программ и идентификаторах,
включая замену русских букв, одинакового с латинскими
написания, на латинские. Контекстные преобразования разделены на блоки,
относящиеся к определенным разделам документации (приводится фрагмент):
Контекст поиска: |
Контекст замены: |
Комментарий: |
|1|%%<hr> |
|
Начало блока 1 |
|1|{[АВЕКМНОРСТХУ
A-Z]+[АВЕКМНОРС ТХУA-Z0-9]*[ |,|.|;|:|&|
(|)|=|@+|@-|*|<|!|@}|^]} |
#[BlockEdit(selcn,sysfile1, _{1}..{1}_)] |
Формирование системного
файла sysfile1
с диапазонами имен п/п и идентификаторов, подлежащих
переводу (поиск проводится по списку возможных прописных русских букв и
диапазону латинских букв), последний перечень символов определяет допустимые
символы, ограничивающие имена и идентификаторы. |
|1|$${<h3> *
Математическое
описание} |
|
Конец блока 1 |
|1|%$ |
#[BlockConv({10},,sysfile1, eneq,dn)] |
Функция перевода символов
с использованием созданного в блоке системного файла sysfile1
. |
|1|%$ |
#[BlockOper(retn)] |
Сдвиг по входному файлу
на одну строку вверх (чтобы повторить чтение конечной строки этого блока). |
|2|%%{<h3> * Математическое
описание} |
|
Начало блока 2 |
|2|{[АВЕКМНОРСТХ A-Z][АВЕКМНОРСТХ A-Z][АВЕКМНОРСТХ A-Z0-9][АВЕКМНОРС
ТХA-Z0-9][СCRD]} |
#[BlockEdit(selcn,sysfile1, _{1}..{1}_)] |
Формирование системного
файла sysfile1
с диапазонами имен п/п. |
|2|$${<h3> *
Использование} |
|
Конец блока 2. |
|2|%$ |
#[BlockConv({10},,sysfile1, eneq,dn)] |
Функция перевода символов
с использованием созданного в блоке системного файла sysfile1
. |
16. Добавление
к именам п/п окончания _c . Контекстные
преобразования разделены на блоки, относящиеся к определенным разделам
документации (приводится фрагмент):
Контекст поиска: |
Контекст замены: |
Комментарий: |
|1|%%<hr> |
|
Начало блока 1 |
|1|{[a-z][a-z][a-z0-9] [a-z0-9][rdci][ |.|)|,|(]} |
#[{1}|1..-2 & "_c" & {1}|-1..-1 //{1}] |
Выделение из найденной
группы символов имени п/п (последний символ группы
не включается) и присоединение к нему _c и
конечного символа группы ( например, из имени Am01r формируется имя Am01r_c ). |
|1|$${<h3> * Использование} |
|
Конец блока 1 |
|1|%$ |
#[BlockOper(repl,{10}, {10})] |
Запись отредактированного
блока в выходной файл. |
|2|%%{<h3> *Параметры} |
|
Начало блока 2 |
|2|{[a-z][a-z0-9]*
}{ *@-$} |
|
Идентификаторы параметров
не изменяются. |
|2|{[a-z][a-z][a-z0-9] [a-z0-9][rdci][ |.|)|,|(]} |
#[{1}|1..-2 & "_c" & {1}|-1..-1 //{1}] |
Добавление к имени п/п окончания _c . |
|2|$${<h3> *Версии} |
|
Конец блока 2. |
|2|%$ |
#[BlockOper(repl,{10}, {10})] |
Запись отредактированного
блока в выходной файл. |
17.
Замена содержимого раздела 'Использование' на обращение к п/п на Си и содержимого раздела 'Пример использования'
на тест к п/п на Си. Эти действие выполняются контекстными преобразованиями:
Контекст поиска: |
Контекст замены: |
Комментарий: |
|1|%%<h3> *
Использование |
|
Начало блока 1 |
|1|$${%\0d\0a} |
|
Конец блока 1 (пустая строка - в начале строки
стоят коды #13#10 ). |
|1|%$ |
#[BlockOper(repl,{{3}}, {10},,2..-2,False)] |
Содержимое третьей ячейки
общего архива замещает строки блока редактирования от второй до
предпоследней, без записи блока в выходной файл (ключ False ). |
|1|%$ |
#[BlockOper(insb,{{2}}, {10},,-1,False)] |
Перед последней строкой
блока вставляется содержимое второй ячейки общего архива ( </pre>
) без записи блока в выходной файл (ключ False
). |
|1|%$ |
#[BlockOper(insb,{{1}}, {10},,2)] |
Перед второй строкой блока
вставляется содержимое первой ячейки общего архива ( <pre>
) и блок записывается в файл. |
|2|%%{<h3> *Пример
использования} |
|
Начало блока 2 |
|2|{% +[АВЕКМНОРСТ ХУA-Z][АВЕКМНОРСТ ХУA-Z0-9]* } |
#[BlockEdit(selsp,sysfile)] |
Формирование системного
файла sysfile,
содержащего номера min
и max
строки блока с оператором языка ФОРТРАН (для строк теста,
начинающихся с идентификатора). |
|2|{% +[0-9]+ +[АВЕКМН
ОРСТХУA-Z]} |
#[BlockEdit(selsp,sysfile)] |
Формирование системного
файла sysfile,
содержащего номера min
и max строки блока с
оператором языка ФОРТРАН (для строк теста, начинающихся с цифровой метки). |
2|$${% *Результат} |
|
Конец блока 2. |
|2|%$ |
#[BlockOper(repl,{{4}}, {10},,&1|sysfile
.. &2|sysfile
)] |
Замена в блоке диапазона
строк, взятого из первой и второй лексем системного файла sysfile,
на содержимое четвертой ячейки общего архива . |
18.
Замена в обращений к первым операторам п/п на языке
ФОРТРАН subroutine fname( … ) на их аналог на языке Си
(п/п может быть версией исходной п/п и ее следует искать непосредственно в
каталоге files_&1|1 под именем fname_c.c, или
содержаться в тесте исходной п/п и ее следует искать в том же каталоге под
именем &3|3 , находящимся в третьей лексеме
файла цикла 3). Эти действия выполняются контекстными преобразованиями:
Контекст поиска: |
Контекст замены: |
Комментарий: |
|1|%%{subroutine}{[a-z]+ [_a-z0-9]*[
|&|(]}{?*)} |
#[{2}|1..-2//{{5}}] |
Начало блока 1: имя п/п выделяется из второй группы (без последнего граничного
с именем символа) и записывается в ячейку пять общего архива. |
|1|$$ |
|
Конец блока 1: строка
совпадает с началом блока, т.к. закрывающая скобка списка параметров
находится в этой же строке. |
|1[file=d:\docci\files_&1|1
\{{5}}.c ::
file=d:\docci\files_&1|1 \&3|3 ] | %$ |
#[BlockFile(extr,sysRcond, {10},"int
{{5}}"::"real {{5}}",")","subroutine",")")
:: BlockFile(extr,sysRcond, {10},"%int
{{5}}_c"::"%real {{5}}_c",")","subroutine",")")] |
Системная переменная sysRcond
формируется в процессе проверки блокового условия и содержит имя файла, по
которому будет производиться поиск контекстов; по номеру выполненного условия
выбирается блоковая функция для работы с эти файлом, производится поиск
контекста по заданным граничным условиям и запись его в блок. |
|2|%%{subroutine} {[a-z]+[_a-z0-9]*[ |&|(]} |
#[{2}|1..-2//{{5}}] |
Начало блока 2: имя п/п выделяется из второй группы (без последнего граничного
с именем символа) и записывается в ячейку пять общего архива. |
|2|$${)} |
|
Конец блока 2: строка не
совпадает с началом блока, т.к. закрывающая скобка находится в другой строке. |
|2[file=d:\docci\files_&1|1
\{{5}}.c :: file=d:\docci\files_&1|1 \&3|3 ]| %$ |
#[BlockFile(extr,sysRcond, {10},"int
{{5}}"::"real {{5}}",")","subroutine",")")
:: BlockFile(extr,sysRcond, {10},"%int
{{5}}_c"::"%real {{5}}_c",")","subroutine",")")] |
Контекстные
преобразования аналогичные преобразования блока 1. |
Завершение
цикла 3:
#КОНЕЦ:3
19.
Создание левого списка файлов htm-файлов каталога d:\docci\cat\&1|1
\
(например, для подкаталога am).
20.
Создание правого абстрактного списка htm-файлов каталога d:\docci\cat\&1|1
\ с добавлением к именам файлов окончания _c
.
21.
Переименование файлов из левого списка в правый (например, Am00r.htm в Am00r_c.htm ).
22.
Перевод имен файлов на нижний регистр в каталоге d:\docci\cat\&1|1
\
(например, . Am00r_c.htm в am00r_c.htm ).
Завершение
цикла 1:
#КОНЕЦ:1
Полный
текст сценария:
teconv.srcc.msu.ru/resurs/docscrpt.html
Иллюстрация перекодировки документации для программ SF60R и sf60r_c :