Примитивы ввода/вывода TeX

Примитивы ввода/вывода TeX

Я хотел бы написать несколько простых макросов для обработки таких вещей, как перекрестные ссылки, чтобы использовать их в простом TeX. (Я знаю, что уже есть макросы, предназначенные для этого, например, те, что есть в Eplain, но я хотел бы попробовать что-то другое самостоятельно.) Поэтому мне нужно знать, как читать из файла и как записывать в файл. Какие примитивы TeX делают такие вещи? Как они работают?

Еще один вопрос: может ли TeX «вызывать» другие программы во время своей работы? Я имею в виду: есть ли в TeX эквивалент системной функции, присутствующей в языке C?

решение1

TeX имеет \readи \writeпримитивы для чтения и записи в файлы, а также, конечно, \inputдля ввода всего файла 'здесь'. Если вы посмотрите, например, на механизм перекрестных ссылок LaTeX, он использует, \writeно избегает использования \read(построчно) в пользу использования \inputс соответствующим образом спроектированными вторичными файлами.

Как \inputдостаточно легко понять, давайте сосредоточимся на \readи \write. Оба они работают с файловым потоком, которому присваивается номер, но обычно выделяется с помощью \new.... Например

\newread\myread
\openin\myread=myinput %

\newwrite\mywrite
\immediate\openout\mywrite=myoutput %

установит чтение с именем \myreadи запись с именем \mywrite. Обратите внимание, что я использовал \immediateс \write: из-за асинхронной природы конструктора страниц TeX, вам нужно убедиться, что вы гарантируете, что \writeоперации происходят в «правильном» месте. (Подробнее об этом ниже.)

С двумя открытыми потоками мы можем, например, записать на выход. Если мы сделаем две записи, одну «сейчас» и одну «отложенную»

\def\foo{a}
\immediate\write\mywrite{\foo}
\write\mywrite{\foo}
\def\foo{b}
Hello
\bye

результат - myoutput.texчтение

a
b

Это потому, что \write\mywriteсоздает whatsit, который выполняется только при отправке страницы. Это полезно, если, например, то, что вам нужно написать, содержит номер страницы, поскольку он известен только на этапе вывода. Также обратите внимание, что \writeдействует как \edef: все расширяется, если вы не запретите это с помощью \noexpandили toks. Обратите внимание, однако, что это расширение выполняется в момент \writeфактического выполнения операции, поэтому необходимо убедиться, что макросы имеют правильные определения при использовании отложенного \write.

Примитив \readчитает одну строку за раз (если только не совпадают фигурные скобки) и токенизирует обычным способом TeX. Вы можете организовать цикл по файлу по одной строке за раз, используя тест \ifeofна \myread, но, как я уже сказал, часто проще просто \inputфайл, содержащий перекрестные ссылки.

Если вы хотите сделать системный вызов, «чистый» TeX не поможет. Однако, Web2c уже давно имеет специальный «поток», позволяющий выйти в систему: \write18. Это риск безопасности, поэтому в качестве стандарта в таком выходе разрешен только ограниченный набор команд. Вы можете сделать, например,

pdftex --shell-escape myfile

разрешить все побеги: риск, если вы написали весь код самостоятельно, заключается только в том, чтобы натворить дел! Выполнение \write18не возвращает ничего обратно в TeX: вам нужно будет организовать чтение результата каким-то образом, возможно, используя \readвторичный файл.

Как отмечено в комментарии, доступно дополнительное расширение синтаксиса \input|"<command>". Это снова ограничено, \write18но предоставляет расширяемый метод для захвата ввода из команд оболочки.

решение2

Другой особой проблемой при работе с перекрестными ссылками через внешний файл является порядок чтения, открытия, записи и закрытия этого файла. Основная схема такова:

\newwrite\fileout  % allocations of the file number

\def...     ... all macros which can be used in the file must be defined
\input file ... input only when file exists (the file doesn't exist at the first run)
            ... this input stores the data from file into internal macros
\immediate\openout\fileout=file  ... this removes the data from file
                                  ... the file has zero length now

... document ... macros used in the document write (typically not immediately) 
                 data to the file

\end ... this closes the file automatically, 
         but if you need to use the data from the file at the end of the document
         (for example the TOC at the end of the document):
\vfil\eject  
\immediate\closeout\fileout
\input file ... this creates the TOC at the end of the file.
\end

Схема выше показывает, что вам нужно создать макрос, который читает файл \inputтолько тогда, когда этот файл существует. Вы можете использовать следующий \softinputмакрос для таких целей:

\newread\testin
\def\softinput #1 {\let\next=\relax \openin\testin=#1
   \ifeof\testin \message{Warning: the file #1 does not exist}%
   \else \closein\testin \def\next{\input #1 }\fi
   \next}

Связанный контент