Hot plugging in a macro-definition Remplacement à chaud dans la définition d’une

macro

Benjamin Bayart^{∗}

2001/01/27

Contents Table des matières

1 ForewordIntroduction  1
2 Hot pluggingRemplacement à chaud  1
3 File limitNombre maximum de fichier  2
4 How it worksComment ça marche  3
5 ImplementationImplémentation  3

1 Foreword Introduction

I’m French. I speak a few words of english. As most of the TEX users are not french, I wrote (or tried to) the documentation in english. But this package is a bit tricky to use, with a lots of side effects, so I prefere to also write the documentation in french. In case the french documentation states something, and the english one states the opposite, the french one is probably right, and you should send me an e-mail to help me improve my english.

2 Hot plugging Remplacement à chaud

The basic idea of this package is rather simple: you want to slightly modify a macro-

L’idée à la base de ce package est assez simple : tu souhaites modifier une macro dont

command you didn’t write (one from the ker- tu n’es pas l’auteur (une macro du noyau
nel, or from a third party package). The usual L^{A}TEX, ou prise dans un autre package). La

∗bayartb@edgard.fdn.fr

way is that you copy the definition and change manière habituelle est de copier la définition
what you want to change. In some cases, there de cette macro dans ton document, puis d’al-
is no better solution. But in simple cases, there térer à loisir la copie. Dans les cas complexes,
is a way to have a better solution. This pack- on ne peut pas faire autrement. Mais dans les
age is to deal with the simple case.  cas simples, une méthode plus élégante est pos-

sible. Ce package présente la méthode élégante pour le cas simple.

This simple case is when the original macro (say \bibliography, the macro command

Le cas simple c’est quand la macro originale (mettons \bibliography, la macro qui

which stand behin \begin{bibliography}) se cache derrière \begin{bibliography}) ap-

call one macro (say \chapter) and you want pelle une macro (disons \chapter) alors que
it to call another one (say \section). For tu veux qu’elle en appelle une autre (disons
this simple example, if you copy the defin- \section). Pour cet exemple simple, si tu co-
ition, then your document might not work pies la définition de \bibliography, ton docu-
with another version of the class. With ment risque de ne plus compiler avec une autre
the hotplug package, you can hotplug the version de la classe. Avec le package hotplug,
\section into \bibliography where was pre- tu peux remplacer à chaud le \chapter qui est

viously \chapter.  dans \bibliography par \section.

To solve this problem, the solution can be:

Pour résoudre ce problème, la solution pourra être :

 \HotReplace\bibliography\chapter\section

3 File limit Nombre maximum de fichier

During \HotReplace we need to have a write file descriptor available. If you give no

Durant le \HotReplace, on a besoin d’un descripteur de fichier en écriture. Si tu ne

options to the package, or the file option, passes pas d’option au package, ou l’option
which is the default, then a \newwrite will file qui est celle pas défaut, le package fera
be issued. It you’re getting short of such appel à \newwrite pour se réserver ad vi-
things (one can only have 16 \newwrite within tam etærnam un tel descripteur. Si tu n’en as
TEX, and L^{A}TEX already uses several), you plus assez (tu ne peux en avoir que 16 dans
can use the option nofile, then the macro TEX, et, L^{A}TEX en consomme déjà quelques
\HotFile will be defined to use the file 15, uns), tu peux utiliser l’option nofile, en pa-
which is choosen arbitrarily. You can then reil cas la macro \HotFile sera définie pour
choose any other file which suits you more. It utiliser le descripteur numéro 15, arbitraire-
will be use only during \HotReplace. It will ment choisi. Tu peux alors choisir n’importe
be open, write and close during each single call quel autre descripteur qui te convienne. Il ne
to \HotReplace, so you can choose the file sera utilisé que pendant \HotReplace. Il sera
descriptor of any file that is not used at the ouvert, écrit, puis refermé, durant chacun des
same time. For example, if you do your calls to appels à \HotReplace, tu peux donc choisir
\HotReplace before the \begin{document}, n’importe quel descripteur qui n’est pas uti-
then, you can call:  lisé en même temps que tu fais tes rempla-

cements. Par exmeple, si tu fais tes appels

                                         à \HotReplace avant le \begin{document},

alors, tu peux faire :

 \usepackage[nofile]{hotplug}

 \makeatletter
 \let\HotFile\ext@toc
 \makeatother

4 How it works Comment ça marche

A technical point you might already know: suppose a \toto macro defined with:

Petit rappel technique : soit une commande \toto définie par :

 \def\toto(#1,#2){bla \bla bla}

The TEX primitive \meaning\toto produces:

La primitive TEX \meaning\toto produit :

 macro:(#1,#2)->bla \bla bla

We will heavily use it.  On va abondament s’en servir.

5 Implementation Implémentation

1 ⟨∗hotplug⟩

 2 \ProvidesPackage{hotplug}[2004/05/31 v1.00 Hot replace in a command def]

3 ⟨/hotplug⟩

\keep@prefix

The L^{A}TEX macro \strip@prefix reads the result of a \meaning and only keep the body

La macro \strip@prefix de L^{A}TEX lit le genre de choses produites par \meaning et ne

of the macro (removing the arguments, it only garde que le corps de la macro (tout ce qui
keeps what is after >). In the same spirit, we est après le >). Dans le même esprit, on défi-
define here a \keep@prefix which keeps this nit \keep@prefix qui garde la définition des
prefix.  arguments.

4 ⟨∗hotplug⟩

 5 \def\keep@prefix #1:#2->#3\finkeep{#2}

6 ⟨/hotplug⟩

\HotReplace

This macro will do the whole job. It uses  C’est cette macro qui fait tout le travail.
a lot of \expandafter, thus it’s almost im- Elle utilise énormément de \expandafter. Elle
possible to read it. It will be commented in est donc presque illisible. Elle sera très com-
details, but remains hard to understand.  mentée, mais pas forcément compréhensible

pour autant.

In the following explanations, we will sup-  Dans les explications, on suppose qu’on fait
pose that the replace is  le changement

 \HotReplace\commande\from\to

7 ⟨∗hotplug⟩

 8 \def\HotReplace#1#2#3{%
 9 % Change #2 pour #3 dans #1

We store the string ##1 in a token register.  On stocke la chaîne ##1 dans un registre de

token.

10 \@temptokena{##1}

The following lines are hard to read. The  Les lignes suivantes sont difficiles à lire.
first part expanded is \string#2, which pro- Le premier morceau exécuté est \string#2,
duces \from as a string (not the token \from). qui produit \from sous forme d’une chaîne
Next is expanded the \the\@temptokena (pas le token \from). Ensuite est exécuté le
which produces the string ##1. Finally, the \the\@temptokena qui produit la chaine ##1.
affectation is donce. So, this is more or less Enfin, l’affectation à lieu, c’est donc vague-
similar to  ment équivalent à

 \@temptokena{##1\from##2\endHplug}

with this restriction that we have the string à cette nuance qu’on a affaire à la chaîne \from

\from and the token \endHplug.  et au token \endHplug.

11 \expandafter\expandafter\expandafter\@temptokena
12 \expandafter\expandafter\expandafter{%
13 \expandafter\the
14 \expandafter\@temptokena
15 \string#2 ##2\endHplug}

What we are trying to do is to define a  Ce qu’on cherche à faire, c’est définir une
macro which look like that:  macro qui soit de cette forme là :

 \def\preHplug#1\from#2\endHplug{\def\tmp@pre{#1}}

where we have the string \from. Such that if où l’on à la chaîne \from. De telle sorte que si
this macro reads the body of \commande, as it cette macro lit le corps de \commande, tel qu’il
is given by \meaning (it gives back a string), est donné par \meaning (la primitive renvoie
we will have in \tmp@pre all the part of the un chaîne), on récupère dans \tmp@pre toute
body that is before \from.  la partie du corps de la macro qui se trouve

avant \from.

The kind of argument expected by this  La forme d’argument attendue par cette
macro is stored in \@temptokena, as we’ve macro est contenue dans \@temptokena, comme
seen before. So, those lines will do the job on vient de voir. Donc ces quelques lignes vont
and define our strange \preHplug.  faire le boulot et définir notre \preHplug.

16 \expandafter\def
17 \expandafter\preHplug
18 \the\@temptokena{\def\tmp@pre{##1}}

Similarily, we build a second macro, but  On crée une seconde macro sur le même
one which stores what is after \from in the modèle mais qui garde tout ce qui se trouve
body of \commande.  après \from dans le corps de \commande.

19 \expandafter\def
20 \expandafter\postHplug
21 \the\@temptokena{\def\tmp@post{##2}}

We now have two funny macros, \preHplug  On se trouve donc à la tête de deux ma-
and \postHplug, which if called properly will cros \preHplug et \postHplug qui, convena-
cut the body of \commande in two pieces.  blement appellées, vont nous découper le corps

de \commande en deux morceaux.

We want to call something like  On cherche donc à appeler un truc du genre

 \preHplug\strip@prefix\meaning\commande\endHplug

to take the beginning of the body (and the pour récupérer le début (et la même chose avec
same with \post), but it needs to be expan- \post), mais il faut exécuter les choses dans
ded in a strange order: first expand \meaning, un ordre bizare : d’abord \meaning, qui va
which will produce the whole text, then produire le texte complet, puis \strip@prefix
\strip@prefix which will remove the part qui va retirer la partie macro:...->, puis enfin
macro:...->, then finaly expand \preHplug. exécuter la macro \preHplug. C’est ce qu’on
This is why there are so many \expandafter. fait avec la multitude de \expandafter.

22 \expandafter\expandafter
23 \expandafter\preHplug
24 \expandafter\strip@prefix
25  \meaning#1\endHplug

We now have in \tmp@pre the body of  On a donc dans \tmp@pre le corps de
the macro \commande up to \from, without la macro jusqu’à \from exclus. On fait le
it. We do the same with \postHplug to get même appel, avec \postHplug pour récupé-

\tmp@post.  rer \tmp@post.

26 \expandafter\expandafter
27 \expandafter\postHplug
28 \expandafter\strip@prefix
29  \meaning#1\endHplug

We now want to get the kind of arguments  On cherche maintenant à récupérer la
expected by \commande, which is a bit easier: forme d’argument attendue par \commande,
\keep@prefix have been previously defined to c’est un tout petit peu plus simple, \keep@prefix,
do that. It works a bit like \preHplug but qui fonctionne un peu comme \preHplug a
was easier do define, the required delimiter in déjà été définie (on pouvait la définir avant,
the arguments (namely the strings : and ->) on connaissait les délimiteurs nécessaires dans
where already known, which is not the case ses arguments, ce qui n’est pas le cas pour
for \preHplug where the delimiter (the string \preHplug).

\from) was only learned recently.

30 \edef\tmp@args{\expandafter\keep@prefix\meaning#1\finkeep}

We now have in \tmp@args the kind of ar-  On a donc maintenant dans \tmp@args
guments of \commande, in \tmp@pre the be- la forme d’arguments de \commande, dans
ginning of its definition, and in \tmp@post the \tmp@pre le début de la définition, et dans
end of its definition.  \tmp@post la fin de cette définition.
We want TEX to read a brand new defini-  On veut que TEX lise une nouvelle défini-
tion of the macro, but now, it have been trans- tion de la macro, mais maintenant que tout
formed in a string. It cannot anymore be cela est sous forme de chaînes, ça n’a aucune
transformed straightly in a real macro. For chance de re-devenir facilement une vraie ma-
that purpose, we are going to write in a file cro. Pour cette raison, on va écrire le texte de
the string which defined the macro, and then notre nouvelle définition dans un fichier, puis

ask TEX to read this brand new file.  demande à TEX de bien vouloir lire ce nouveau

fichier.

We are going to write in a temporary file a  On va écrire dans un fichier temporaire la
string like  forme suivante

 \def\commande\tmp@args{\tmp@pre\to\tmp@post}

string in which all the macros a expanded to forme dans laquelle toutes les macros sont
their definitions, except \def, \commande, and remplacées par leur définition sauf \def,
\to, and where the braces are kept.  \commande, et \to et où les accolades sont

conservées.

First, we open the file:  On commence par ouvrir le fichier :

31 \immediate\openout\HotFile hotplug.tmp\relax

Then, we write, with \noexpand before the  Puis on fait l’écriture, en mettant des
part to be kept unchanged (the three macros \noexpand devant tout ce qu’on souhaite
and the braces).  conserver tel quel (les trois commandes et les

deux accolades).

32 \immediate\write\HotFile{%
33  \noexpand\def
34  \noexpand#1%
35  \tmp@args\noexpand{\tmp@pre\noexpand#3\tmp@post\noexpand}}\relax
36 \immediate\closeout\HotFile

Now, the file contains TEX code which, if  Maintenant, le fichier contient du code
read, will redefine \commande while changing TEX qui, s’il était lu redéfinirait \commande
the first appearance of \from by \to. So we en ayant remplacé la première occurence de
do, and the job is ended.  \from par \to. On va donc s’empresser de lire

le fichier, et le tour sera joué.

37 \input{hotplug.tmp}

38 } 39 ⟨/hotplug⟩

The last thing to be done is to allocate a write handle for our temporary file. Our file is

Il ne nous reste plus qu’à définir le fichier temporaire dans lequel on écrite. Ce fichier est

really temporary, since it is only used during vraiment temporaire, il ne peut être utilisé que
the use of the macro itself. If you run short pendant l’exécution de la macro \HotReplace.
of files in your document (which is often my Si tu es as cours de fichiers (comme c’est sou-
case), then you can bypass this by using any vent mon cas), alors du peux éviter cette al-
other file descriptor which is not used when location, et utiliser tout autre descripteur de
you call \HotReplace.  fichier qui n’est pas utile pendant que tu uti-

                                         lises \HotReplace.

40 ⟨∗hotplug⟩

41 \DeclareOption{nofile}{\hotfilefalse}
42 \DeclareOption{file}{\hotfilefalse}
43 \newif\ifhotfile
44 \hotfiletrue
45 \ProcessOptions
46 \ifhotfile
47 \newwrite\HotFile

48 \else
49 \chardef\HotFile15\relax
50 \fi

51 ⟨/hotplug⟩

Index

Numbers written in italic refer to the page where the corresponding entry is described; numbers underlined refer to the code line of the definition; numbers in roman refer to the code lines where the entry is used.

Symbols

\@temptokena . . . . . . . . . . . . 10, 11, 14, 18, 21

C

\chardef . . . . . . . . . . . . . . . . . . . . . . . . . . 49 \closeout . . . . . . . . . . . . . . . . . . . . . . . . . 36

D

\DeclareOption . . . . . . . . . . . . . . . . . . 41, 42 \def . . . . . . . . . . . . . . . . 5, 8, 16, 18, 19, 21, 33

E

\edef . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 30 \else . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 48 \endHplug . . . . . . . . . . . . . . . . . . . . 15, 25, 29 \expandafter . . . . . . . . . . . . . . . . . . . . . . .

. . 11–14, 16, 17, 19, 20, 22–24, 26–28, 30

F

\fi . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 50 \finkeep . . . . . . . . . . . . . . . . . . . . . . . . 5, 30

H

\HotFile . . . . . . . . . . . . . . . 31, 32, 36, 47, 49 \hotfilefalse . . . . . . . . . . . . . . . . . . . 41, 42 \hotfiletrue . . . . . . . . . . . . . . . . . . . . . . . 44 \HotReplace . . . . . . . . . . . . . . . . . . . . . . . . . \underline{7}

I

\ifhotfile . . . . . . . . . . . . . . . . . . . . . 43, 46 \immediate . . . . . . . . . . . . . . . . . . . 31, 32, 36 \input . . . . . . . . . . . . . . . . . . . . . . . . . . . . 37

K

\keep@prefix . . . . . . . . . . . . . . . . . . . . . \underline{4}, 30

M \meaning . . . . . . . . . . . . . . . . . . . . . 25, 29, 30

N \newif . . . . . . . . . . . . . . . . . . . . . . . . . . . . 43 \newwrite . . . . . . . . . . . . . . . . . . . . . . . . . 47 \noexpand . . . . . . . . . . . . . . . . . . . . . . . 33–35

O \openout . . . . . . . . . . . . . . . . . . . . . . . . . . 31

P \postHplug . . . . . . . . . . . . . . . . . . . . . 20, 27 \preHplug . . . . . . . . . . . . . . . . . . . . . . 17, 23 \ProcessOptions . . . . . . . . . . . . . . . . . . . . 45 \ProvidesPackage . . . . . . . . . . . . . . . . . . . . 2

R \relax . . . . . . . . . . . . . . . . . . . . . . . 31, 35, 49

S \string . . . . . . . . . . . . . . . . . . . . . . . . . . . 15 \strip@prefix . . . . . . . . . . . . . . . . . . . 24, 28

T \the . . . . . . . . . . . . . . . . . . . . . . . . . 13, 18, 21 \tmp@args . . . . . . . . . . . . . . . . . . . . . . 30, 35 \tmp@post . . . . . . . . . . . . . . . . . . . . . . 21, 35 \tmp@pre . . . . . . . . . . . . . . . . . . . . . . . 18, 35

W \write . . . . . . . . . . . . . . . . . . . . . . . . . . . . 32