-
Notifications
You must be signed in to change notification settings - Fork 0
/
Week9.tex
297 lines (252 loc) · 11.4 KB
/
Week9.tex
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
\documentclass[autodetect-engine,dvipdfmx]{jsarticle}
\usepackage{okumacro}
\usepackage[top=25truemm,bottom=25truemm,left=25truemm,right=25truemm]{geometry}
\usepackage[dvipdfmx]{xcolor}
\usepackage{ascmac}
\usepackage{listings,jlisting}
\usepackage{latexltx2015}
\begin{document}
\title{ latex.ltxリーディング \\ 第9回資料 }
\author{ 東大\TeX 愛好会 }
\date{2015年12月14日}
\maketitle
\section{エラーメッセージまわりその2(大浦)}
\texttt{lterror.dtx}に由来する部分を読んでいく。定義の前半の2回目。
\subsection{GenericError続論}
Errorの続きをやる。定義:
\latexltx
\begin{lstlisting}[firstnumber=893]
\bgroup
\lccode`\@=`\ %
\lccode`\~=`\ %
\lccode`\}=`\ %
\lccode`\{=`\ %
\lccode`\T=`\T%
\lccode`\H=`\H%
\catcode`\ =11\relax%
\lowercase{%
\egroup%
\dimen@\ifx\@TeXversion\@undefined4\else\@TeXversion\fi\p@%
\ifdim\dimen@>3.14\p@%
\DeclareRobustCommand{\GenericError}[4]{%
\begingroup%
\immediate\write\@unused{}%
\def\MessageBreak{^^J}%
\set@display@protect%
\edef%
\@err@ %
{{#4}}%
\errhelp
\@err@ %
\let
\@err@ %
\@empty
\def\MessageBreak{^^J#1}%
\def~{\errmessage{%
#2.^^J^^J%
#3^^J%
Type H <return> for immediate help%
\@err@ %
}}%
~%
\endgroup}%
\else%
\DeclareRobustCommand{\GenericError}[4]{%
\begingroup%
\immediate\write\@unused{}%
\def\MessageBreak{^^J}%
\set@display@protect%
\edef%
\@err@ %
{{#4}}%
\errhelp
\@err@ %
\let
\@err@ %
\errmessage
\def\MessageBreak{^^J#1}%
\def~{\typeout{! %
#2.^^J^^J%
#3^^J%
Type H <return> for immediate help.}%
\@err@ %
{}}%
~%
\endgroup}%
\fi}%
\end{lstlisting}
であった。903〜905で条件分岐があり,\TeX バージョンが3.14より大きいかどうかで場合分けされることを述べた。(ちなみに,バージョンが不明の場合にはバージョン4として扱われる。)今回は,それぞれの場合について,\cmd{GenericError}の定義がどのようになっているかを具体的に見ていくことにする。
\subsection{条件分岐1:バージョンが3.14より大きいとき}
\latexltx
\begin{lstlisting}[firstnumber=905]
\DeclareRobustCommand{\GenericError}[4]{%
\begingroup%
\immediate\write\@unused{}%
\def\MessageBreak{^^J}%
\set@display@protect%
\edef%
\@err@ %
{{#4}}%
\errhelp
\@err@ %
\let
\@err@ %
\@empty
\def\MessageBreak{^^J#1}%
\def~{\errmessage{%
#2.^^J^^J%
#3^^J%
Type H <return> for immediate help%
\@err@ %
}}%
~%
\endgroup}%
\end{lstlisting}
905行目で,\cmd{GenericError}は引数を四つとる堅牢な制御綴として定義されることが宣言される。907行目の,\cmd{immediate}\cmd{write}\cmd{@unused}については前回資料で述べた通り,そのあとの内容をターミナル送りなり\texttt{.log}ファイル送りなりにしてくれるコマンドなのだが,ここではその引数が空なので結局どうでもよい。その次の908行目で,\preSub\verb|^^J|\preSub つまり改行をエラーメッセージの区切りとして指定し,その次の909行目\cmd{set@display@protect}で,\cmd{protect}を\cmd{string}の別名として定義する(前回資料で扱った)。
そして4番目の引数を\cmd{@err@}に展開した形で渡し,\cmd{errhelp}\cmd{@err@}を実行した上で\cmd{@err@}を\cmd{@empty}に,つまり空に戻しておく\footnote{念のため。\cmd{@empty}は\texttt{latex.ltx}の122行目に空の綴りとして定義されている。}。\cmd{errhelp}は引数を一つ取るプリミティブで,エラーメッセージが出たあと,hキー+Returnキーを押した場合に表示されるメッセージを指定するコマンドである。ここまでではエラーメッセージの区切りは改行のままである。
さて,ここでエラーメッセージの区切りの変更(918行目)となる。ただの改行\preSub\verb|^^J|\preSub に飽き足らず第一引数まで含めた\preSub\verb|^^J#1|\preSub をエラーメッセージとして定義する。その上で\~(チルダマーク)の定義を変更して,これが
\texsource
\begin{lstlisting}
\errmessage{%
#2.^^J^^J%
#3^^J%
Type H <return> for immediate help%
\@err@ %
}
\end{lstlisting}
の意味だというふうに定義してしまう。\cmd{errmessage}は,ターミナル及び\texttt{.log}ファイルに送られるエラーメッセージを指定するプリミティブである。923行目の\cmd{@err@}については,すでに空になっているはずなので,考える必要はない。
そして,925行目で,今定義した\~(チルダマーク)を使ってエラーメッセージを生成し,終了となる。
では,実際の例を見てみよう。
\subsection{(条件分岐1)実際例として}
実際例として,\texttt{latex.ltx}1062行目で定義されている\cmd{@nocounterr}を取り上げる。ソース☆0:
\texsource
\begin{lstlisting}
\@nocounterr{ほげ}
\end{lstlisting}
を展開してみることにしよう。つまり,「ほげ」という名前のカウンタが定義されていなかったのに,
\texsource
\begin{lstlisting}
\setcounter{ほげ}{10}
\end{lstlisting}
のようにあたかも「ほげ」という名前のカウンタがあるかのように書いてしまっったときに生成されるエラーの生成機序を追っていこうということである。まず,\cmd{@nocounterr}は次のように定義されている。
\latexltx
\begin{lstlisting}[firstnumber=1062]
\gdef\@nocounterr#1{%
\@latex@error{No counter '#1' defined}\@eha}
\end{lstlisting}
これより,ソース☆0は,一段階展開されて次のソース☆1となる。
\texsource
\begin{lstlisting}
\@latex@error{No counter 'ほげ' defined}\@eha}
\end{lstlisting}
ここで,\cmd{@latex@error}が展開される。\cmd{@latex@error}は,1003行目に,次のように定義されている。
\latexltx
\begin{lstlisting}[firstnumber=1003]
\gdef\@latex@error#1#2{%
\GenericError{%
\space\space\space\@spaces\@spaces\@spaces
}{%
LaTeX Error: #1%
}{%
See the LaTeX manual or LaTeX Companion for explanation.%
}{#2}%
}
\end{lstlisting}
これより,ソース☆1はもう一段階展開されて次のソース☆2となる。
\texsource
\begin{lstlisting}
\GenericError{%
\space\space\space\@spaces\@spaces\@spaces
}{%
LaTeX Error: No counter 'ほげ' defined%
}{%
See the LaTeX manual or LaTeX Companion for explanation.%
}{\@eha}%
\end{lstlisting}
そしてお待ちかね\cmd{GenericError}の展開となる。
展開結果は次のようなソース☆3。
\texsource
\begin{lstlisting}
\begingroup%
\immediate\write\@unused{}%
\def\MessageBreak{^^J}%
\set@display@protect%
\edef%
\@err@ %
{{\@eha}}%
\errhelp
\@err@ %
\let
\@err@ %
\@empty
\def\MessageBreak{^^J\space\space\space\@spaces\@spaces\@spaces}%
\def~{\errmessage{%
LaTeX Error: No counter 'ほげ' defined.^^J^^J%
See the LaTeX manual or LaTeX Companion for explanation.^^J%
Type H <return> for immediate help%
\@err@ %
}}%
~%
\endgroup
\end{lstlisting}
つまり,こういうこと。
hキー+Returnキーを押したときに表示されるヘルプメッセージの内容は,\cmd{@eha}になり,その区切り記号は改行である。
エラーメッセージの内容は,LaTeX Error〜immediate helpであり,その区切り記号は改行+\cmd{space}$\times3$+\cmd{@spaces}$\times3$である。
さて,\cmd{@eha},\cmd{space},\cmd{@spaces}という三つの初出コマンドが出てきたので一つずつ解説を加えよう。
\cmd{@eha}については,別途\texttt{latex.ltx}に定義がある。
\latexltx
\begin{lstlisting}[firstnumber=1041]
\gdef\@eha{%
Your command was ignored.\MessageBreak
Type \space I <command> <return> \space to replace it %
with another command,\MessageBreak
or \space <return> \space to continue without it.}
\end{lstlisting}
この時点では\cmd{MessageBreak}はただの改行なので,\cmd{MessageBreak}は改行に読み替えておけば良いし,\cmd{space}については後述する通りただの半角スペースなのでそう読み替えておけば良い。
\cmd{space}についても,別途\texttt{latex.ltx}に定義がある。
\latexltx
\begin{lstlisting}[firstnumber=97]
\def\space{ }
\end{lstlisting}
ただの半角スペースじゃないか。
\cmd{@spaces}も\texttt{latex.ltx}由来のコマンドで,\cmd{@eha}を定義したすぐ上流の1040行目に定義されている。
\latexltx
\begin{lstlisting}[firstnumber=1040]
\def\@spaces{\space\space\space\space}
\end{lstlisting}
ただの半角スペース4こ連続じゃないか。
\subsection{条件分岐2:バージョンが3.14より小さいとき}
\cmd{GenericError}の定義はこんな感じに変わる。
\latexltx
\begin{lstlisting}[firstnumber=928]
\DeclareRobustCommand{\GenericError}[4]{%
\begingroup%
\immediate\write\@unused{}%
\def\MessageBreak{^^J}%
\set@display@protect%
\edef%
\@err@ %
{{#4}}%
\errhelp
\@err@ %
\let
\@err@ %
\errmessage
\def\MessageBreak{^^J#1}%
\def~{\typeout{! %
#2.^^J^^J%
#3^^J%
Type H <return> for immediate help.}%
\@err@ %
{}}%
~%
\endgroup}%
\end{lstlisting}
\cmd{@err@}に第4引数を代入して,それをヘルプメッセージとして指定するところまでは同じである。そこからさきが若干異なる。\cmd{let}を使って,\cmd{@err@}を空にするのではなく\cmd{errmessage}の別名として定義し,次の\cmd{typeout}命令の中で使えるようにしてしまう。
さて942行目からは先ほどの\cmd{errmessage}コマンドにかわり\cmd{typeout}命令に変わっている。これは\texttt{latex.ltx}に定義されたコマンドで,
\latexltx
\begin{lstlisting}[firstnumber=93]
\def\typeout{\immediate\write17}
\end{lstlisting}
となっている。\cmd{write}のあとに続く数が15より大きいので,\cmd{typeout}の引数は,\texttt{.log}ファイル送りになりかつ,ターミナルに表示される。また,\cmd{@err@}は空ではないので今回は考える必要が生じるように思われるものの,今それは\cmd{errmessage}の別名であり,その引数もないので,結局考えなくて済んでしまう。
\end{document}