1 /* $NetBSD: cmds.c,v 1.2 2016/01/14 00:34:53 christos Exp $ */
2
3 /* cmds.c -- Texinfo commands.
4 Id: cmds.c,v 1.55 2004/12/14 00:15:36 karl Exp
5
6 Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003, 2004 Free Software
7 Foundation, Inc.
8
9 This program is free software; you can redistribute it and/or modify
10 it under the terms of the GNU General Public License as published by
11 the Free Software Foundation; either version 2, or (at your option)
12 any later version.
13
14 This program is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 GNU General Public License for more details.
18
19 You should have received a copy of the GNU General Public License
20 along with this program; if not, write to the Free Software Foundation,
21 Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
22
23 #include "system.h"
24 #include "cmds.h"
25 #include "defun.h"
26 #include "files.h"
27 #include "footnote.h"
28 #include "html.h"
29 #include "insertion.h"
30 #include "lang.h"
31 #include "macro.h"
32 #include "makeinfo.h"
33 #include "node.h"
34 #include "sectioning.h"
35 #include "toc.h"
36 #include "xml.h"
37
38 #ifdef TM_IN_SYS_TIME
39 #include <sys/time.h>
40 #else
41 #include <time.h>
42 #endif
43
44 /* Options. */
45 static void cm_exampleindent (void),
46 cm_firstparagraphindent (void),
47 cm_paragraphindent (void),
48 cm_novalidate (void);
49
50 /* Internals. */
51 static void cm_obsolete (int arg, int start, int end),
52 not_fixed_width (int arg);
53
54 /* The dispatch table. */
55 COMMAND command_table[] = {
56 { "\t", insert_space, NO_BRACE_ARGS },
57 { "\n", insert_space, NO_BRACE_ARGS },
58 { " ", insert_space, NO_BRACE_ARGS },
59 { "!", cm_punct, NO_BRACE_ARGS },
60 { "\"", cm_accent_umlaut, MAYBE_BRACE_ARGS },
61 { "'", cm_accent_acute, MAYBE_BRACE_ARGS },
62 { "*", cm_asterisk, NO_BRACE_ARGS },
63 { ",", cm_accent_cedilla, MAYBE_BRACE_ARGS },
64 { "-", cm_no_op, NO_BRACE_ARGS },
65 { ".", cm_punct, NO_BRACE_ARGS },
66 { "/", cm_no_op, NO_BRACE_ARGS },
67 { ":", cm_colon, NO_BRACE_ARGS },
68 { "=", cm_accent, MAYBE_BRACE_ARGS },
69 { "?", cm_punct, NO_BRACE_ARGS },
70 { "@", insert_self, NO_BRACE_ARGS },
71 { "\\", insert_self, NO_BRACE_ARGS },
72 { "^", cm_accent_hat, MAYBE_BRACE_ARGS },
73 { "`", cm_accent_grave, MAYBE_BRACE_ARGS },
74 { "{", insert_self, NO_BRACE_ARGS },
75 { "|", cm_no_op, NO_BRACE_ARGS },
76 { "}", insert_self, NO_BRACE_ARGS },
77 { "~", cm_accent_tilde, MAYBE_BRACE_ARGS },
78 { "AA", cm_special_char, BRACE_ARGS },
79 { "AE", cm_special_char, BRACE_ARGS },
80 { "H", cm_accent, MAYBE_BRACE_ARGS },
81 { "L", cm_special_char, BRACE_ARGS },
82 { "LaTeX", cm_LaTeX, BRACE_ARGS },
83 { "O", cm_special_char, BRACE_ARGS },
84 { "OE", cm_special_char, BRACE_ARGS },
85 { "TeX", cm_TeX, BRACE_ARGS },
86 { "aa", cm_special_char, BRACE_ARGS },
87 { "abbr", cm_abbr, BRACE_ARGS },
88 { "acronym", cm_acronym, BRACE_ARGS },
89 { "ae", cm_special_char, BRACE_ARGS },
90 { "afivepaper", cm_ignore_line, NO_BRACE_ARGS },
91 { "afourlatex", cm_ignore_line, NO_BRACE_ARGS },
92 { "afourpaper", cm_ignore_line, NO_BRACE_ARGS },
93 { "afourwide", cm_ignore_line, NO_BRACE_ARGS },
94 { "alias", cm_alias, NO_BRACE_ARGS },
95 { "anchor", cm_anchor, BRACE_ARGS },
96 { "appendix", cm_appendix, NO_BRACE_ARGS },
97 { "appendixsection", cm_appendixsec, NO_BRACE_ARGS },
98 { "appendixsec", cm_appendixsec, NO_BRACE_ARGS },
99 { "appendixsubsec", cm_appendixsubsec, NO_BRACE_ARGS },
100 { "appendixsubsubsec", cm_appendixsubsubsec, NO_BRACE_ARGS },
101 { "asis", cm_no_op, BRACE_ARGS },
102 { "author", cm_author, NO_BRACE_ARGS },
103 { "b", cm_b, BRACE_ARGS },
104 { "bullet", cm_bullet, BRACE_ARGS },
105 { "bye", cm_bye, NO_BRACE_ARGS },
106 { "c", cm_comment, NO_BRACE_ARGS },
107 { "caption", cm_caption, BRACE_ARGS },
108 { "cartouche", cm_cartouche, NO_BRACE_ARGS },
109 { "center", cm_center, NO_BRACE_ARGS },
110 { "centerchap", cm_unnumbered, NO_BRACE_ARGS },
111 { "chapheading", cm_chapheading, NO_BRACE_ARGS },
112 { "chapter", cm_chapter, NO_BRACE_ARGS },
113 { "cindex", cm_cindex, NO_BRACE_ARGS },
114 { "cite", cm_cite, BRACE_ARGS },
115 { "clear", cm_clear, NO_BRACE_ARGS },
116 { "code", cm_code, BRACE_ARGS },
117 { "comma", cm_comma, BRACE_ARGS },
118 { "command", cm_code, BRACE_ARGS },
119 { "comment", cm_comment, NO_BRACE_ARGS },
120 { "contents", cm_contents, NO_BRACE_ARGS },
121 { "copying", cm_copying, NO_BRACE_ARGS },
122 { "copyright", cm_copyright, BRACE_ARGS },
123 { "ctrl", cm_obsolete, BRACE_ARGS },
124 { "defcodeindex", cm_defcodeindex, NO_BRACE_ARGS },
125 { "defcv", cm_defun, NO_BRACE_ARGS },
126 { "defcvx", cm_defun, NO_BRACE_ARGS },
127 { "deffn", cm_defun, NO_BRACE_ARGS },
128 { "deffnx", cm_defun, NO_BRACE_ARGS },
129 { "defindex", cm_defindex, NO_BRACE_ARGS },
130 { "definfoenclose", cm_definfoenclose, NO_BRACE_ARGS },
131 { "defivar", cm_defun, NO_BRACE_ARGS },
132 { "defivarx", cm_defun, NO_BRACE_ARGS },
133 { "defmac", cm_defun, NO_BRACE_ARGS },
134 { "defmacx", cm_defun, NO_BRACE_ARGS },
135 { "defmethod", cm_defun, NO_BRACE_ARGS },
136 { "defmethodx", cm_defun, NO_BRACE_ARGS },
137 { "defop", cm_defun, NO_BRACE_ARGS },
138 { "defopt", cm_defun, NO_BRACE_ARGS },
139 { "defoptx", cm_defun, NO_BRACE_ARGS },
140 { "defopx", cm_defun, NO_BRACE_ARGS },
141 { "defspec", cm_defun, NO_BRACE_ARGS },
142 { "defspecx", cm_defun, NO_BRACE_ARGS },
143 { "deftp", cm_defun, NO_BRACE_ARGS },
144 { "deftpx", cm_defun, NO_BRACE_ARGS },
145 { "deftypecv", cm_defun, NO_BRACE_ARGS },
146 { "deftypecvx", cm_defun, NO_BRACE_ARGS },
147 { "deftypefn", cm_defun, NO_BRACE_ARGS },
148 { "deftypefnx", cm_defun, NO_BRACE_ARGS },
149 { "deftypefun", cm_defun, NO_BRACE_ARGS },
150 { "deftypefunx", cm_defun, NO_BRACE_ARGS },
151 { "deftypeivar", cm_defun, NO_BRACE_ARGS },
152 { "deftypeivarx", cm_defun, NO_BRACE_ARGS },
153 { "deftypemethod", cm_defun, NO_BRACE_ARGS },
154 { "deftypemethodx", cm_defun, NO_BRACE_ARGS },
155 { "deftypeop", cm_defun, NO_BRACE_ARGS },
156 { "deftypeopx", cm_defun, NO_BRACE_ARGS },
157 { "deftypevar", cm_defun, NO_BRACE_ARGS },
158 { "deftypevarx", cm_defun, NO_BRACE_ARGS },
159 { "deftypevr", cm_defun, NO_BRACE_ARGS },
160 { "deftypevrx", cm_defun, NO_BRACE_ARGS },
161 { "defun", cm_defun, NO_BRACE_ARGS },
162 { "defunx", cm_defun, NO_BRACE_ARGS },
163 { "defvar", cm_defun, NO_BRACE_ARGS },
164 { "defvarx", cm_defun, NO_BRACE_ARGS },
165 { "defvr", cm_defun, NO_BRACE_ARGS },
166 { "defvrx", cm_defun, NO_BRACE_ARGS },
167 { "detailmenu", cm_detailmenu, NO_BRACE_ARGS },
168 { "dfn", cm_dfn, BRACE_ARGS },
169 { "dircategory", cm_dircategory, NO_BRACE_ARGS },
170 { "direntry", cm_direntry, NO_BRACE_ARGS },
171 { "display", cm_display, NO_BRACE_ARGS },
172 { "dmn", cm_dmn, BRACE_ARGS },
173 { "docbook", cm_docbook, NO_BRACE_ARGS },
174 { "documentdescription", cm_documentdescription, NO_BRACE_ARGS },
175 { "documentencoding", cm_documentencoding, NO_BRACE_ARGS },
176 { "documentlanguage", cm_documentlanguage, NO_BRACE_ARGS },
177 { "dotaccent", cm_accent, MAYBE_BRACE_ARGS },
178 { "dotless", cm_dotless, BRACE_ARGS },
179 { "dots", cm_dots, BRACE_ARGS },
180 { "email", cm_email, BRACE_ARGS },
181 { "emph", cm_emph, BRACE_ARGS },
182 { "end", cm_end, NO_BRACE_ARGS },
183 { "enddots", cm_enddots, BRACE_ARGS },
184 { "enumerate", cm_enumerate, NO_BRACE_ARGS },
185 { "env", cm_code, BRACE_ARGS },
186 { "equiv", cm_equiv, BRACE_ARGS },
187 { "error", cm_error, BRACE_ARGS },
188 { "euro", cm_special_char, BRACE_ARGS },
189 { "evenfooting", cm_ignore_line, NO_BRACE_ARGS },
190 { "evenheading", cm_ignore_line, NO_BRACE_ARGS },
191 { "everyfooting", cm_ignore_line, NO_BRACE_ARGS },
192 { "everyheading", cm_ignore_line, NO_BRACE_ARGS },
193 { "example", cm_example, NO_BRACE_ARGS },
194 { "exampleindent", cm_exampleindent, NO_BRACE_ARGS },
195 { "exclamdown", cm_special_char, BRACE_ARGS },
196 { "exdent", cm_exdent, NO_BRACE_ARGS },
197 { "expansion", cm_expansion, BRACE_ARGS },
198 { "file", cm_code, BRACE_ARGS },
199 { "finalout", cm_no_op, NO_BRACE_ARGS },
200 { "findex", cm_findex, NO_BRACE_ARGS },
201 { "firstparagraphindent", cm_firstparagraphindent, NO_BRACE_ARGS },
202 { "float", cm_float, NO_BRACE_ARGS },
203 { "flushleft", cm_flushleft, NO_BRACE_ARGS },
204 { "flushright", cm_flushright, NO_BRACE_ARGS },
205 { "footnote", cm_footnote, NO_BRACE_ARGS}, /* self-arg eater */
206 { "footnotestyle", cm_footnotestyle, NO_BRACE_ARGS },
207 { "format", cm_format, NO_BRACE_ARGS },
208 { "ftable", cm_ftable, NO_BRACE_ARGS },
209 { "group", cm_group, NO_BRACE_ARGS },
210 { "heading", cm_heading, NO_BRACE_ARGS },
211 { "headings", cm_ignore_line, NO_BRACE_ARGS },
212 { "headitem", cm_headitem, NO_BRACE_ARGS },
213 { "html", cm_html, NO_BRACE_ARGS },
214 { "hyphenation", cm_ignore_arg, BRACE_ARGS },
215 { "i", cm_i, BRACE_ARGS },
216 { "ifclear", cm_ifclear, NO_BRACE_ARGS },
217 { "ifeq", cm_ifeq, NO_BRACE_ARGS },
218 { "ifdocbook", cm_ifdocbook, NO_BRACE_ARGS },
219 { "ifhtml", cm_ifhtml, NO_BRACE_ARGS },
220 { "ifinfo", cm_ifinfo, NO_BRACE_ARGS },
221 { "ifnotdocbook", cm_ifnotdocbook, NO_BRACE_ARGS },
222 { "ifnothtml", cm_ifnothtml, NO_BRACE_ARGS },
223 { "ifnotinfo", cm_ifnotinfo, NO_BRACE_ARGS },
224 { "ifnotplaintext", cm_ifnotplaintext, NO_BRACE_ARGS },
225 { "ifnottex", cm_ifnottex, NO_BRACE_ARGS },
226 { "ifnotxml", cm_ifnotxml, NO_BRACE_ARGS },
227 { "ifplaintext", cm_ifplaintext, NO_BRACE_ARGS },
228 { "ifset", cm_ifset, NO_BRACE_ARGS },
229 { "iftex", cm_iftex, NO_BRACE_ARGS },
230 { "ifxml", cm_ifxml, NO_BRACE_ARGS },
231 { "ignore", command_name_condition, NO_BRACE_ARGS },
232 { "image", cm_image, BRACE_ARGS },
233 { "include", cm_include, NO_BRACE_ARGS },
234 { "indent", cm_indent, NO_BRACE_ARGS },
235 { "indicateurl", cm_indicate_url, BRACE_ARGS },
236 { "inforef", cm_inforef, BRACE_ARGS },
237 { "insertcopying", cm_insert_copying, NO_BRACE_ARGS },
238 { "item", cm_item, NO_BRACE_ARGS },
239 { "itemize", cm_itemize, NO_BRACE_ARGS },
240 { "itemx", cm_itemx, NO_BRACE_ARGS },
241 { "kbd", cm_kbd, BRACE_ARGS },
242 { "kbdinputstyle", cm_ignore_line, NO_BRACE_ARGS },
243 { "key", cm_key, BRACE_ARGS },
244 { "kindex", cm_kindex, NO_BRACE_ARGS },
245 { "l", cm_special_char, BRACE_ARGS },
246 { "lisp", cm_lisp, NO_BRACE_ARGS },
247 { "listoffloats", cm_listoffloats, NO_BRACE_ARGS },
248 { "lowersections", cm_lowersections, NO_BRACE_ARGS },
249 { "macro", cm_macro, NO_BRACE_ARGS },
250 { "majorheading", cm_majorheading, NO_BRACE_ARGS },
251 { "math", cm_math, BRACE_ARGS },
252 { "menu", cm_menu, NO_BRACE_ARGS },
253 { "minus", cm_minus, BRACE_ARGS },
254 { "multitable", cm_multitable, NO_BRACE_ARGS },
255 { "need", cm_ignore_line, NO_BRACE_ARGS },
256 { "node", cm_node, NO_BRACE_ARGS },
257 { "noindent", cm_noindent_cmd, NO_BRACE_ARGS },
258 { "novalidate", cm_novalidate, NO_BRACE_ARGS },
259 { "nwnode", cm_node, NO_BRACE_ARGS },
260 { "o", cm_special_char, BRACE_ARGS },
261 { "oddfooting", cm_ignore_line, NO_BRACE_ARGS },
262 { "oddheading", cm_ignore_line, NO_BRACE_ARGS },
263 { "oe", cm_special_char, BRACE_ARGS },
264 { "option", cm_code, BRACE_ARGS },
265 { "ordf", cm_special_char, BRACE_ARGS },
266 { "ordm", cm_special_char, BRACE_ARGS },
267 { "page", cm_no_op, NO_BRACE_ARGS },
268 { "pagesizes", cm_ignore_line, NO_BRACE_ARGS },
269 { "paragraphindent", cm_paragraphindent, NO_BRACE_ARGS },
270 { "pindex", cm_pindex, NO_BRACE_ARGS },
271 { "point", cm_point, BRACE_ARGS },
272 { "pounds", cm_special_char, BRACE_ARGS },
273 { "print", cm_print, BRACE_ARGS },
274 { "printindex", cm_printindex, NO_BRACE_ARGS },
275 { "pxref", cm_pxref, BRACE_ARGS },
276 { "questiondown", cm_special_char, BRACE_ARGS },
277 { "quotation", cm_quotation, NO_BRACE_ARGS },
278 { "r", cm_r, BRACE_ARGS },
279 { "raisesections", cm_raisesections, NO_BRACE_ARGS },
280 { "ref", cm_ref, BRACE_ARGS },
281 { "refill", cm_no_op, NO_BRACE_ARGS },
282 { "registeredsymbol", cm_registeredsymbol, BRACE_ARGS },
283 { "result", cm_result, BRACE_ARGS },
284 { "ringaccent", cm_accent, MAYBE_BRACE_ARGS },
285 { "rmacro", cm_rmacro, NO_BRACE_ARGS },
286 { "samp", cm_code, BRACE_ARGS },
287 { "sansserif", cm_sansserif, BRACE_ARGS },
288 { "sc", cm_sc, BRACE_ARGS },
289 { "section", cm_section, NO_BRACE_ARGS },
290 { "set", cm_set, NO_BRACE_ARGS },
291 { "setchapternewpage", cm_ignore_line, NO_BRACE_ARGS },
292 { "setchapterstyle", cm_obsolete, NO_BRACE_ARGS },
293 { "setcontentsaftertitlepage", cm_no_op, NO_BRACE_ARGS },
294 { "setfilename", cm_setfilename, NO_BRACE_ARGS },
295 { "setshortcontentsaftertitlepage", cm_no_op, NO_BRACE_ARGS },
296 { "settitle", cm_settitle, NO_BRACE_ARGS },
297 { "shortcaption", cm_caption, BRACE_ARGS },
298 { "shortcontents", cm_contents, NO_BRACE_ARGS },
299 { "shorttitlepage", cm_ignore_line, NO_BRACE_ARGS },
300 { "slanted", cm_slanted, BRACE_ARGS },
301 { "smallbook", cm_ignore_line, NO_BRACE_ARGS },
302 { "smalldisplay", cm_smalldisplay, NO_BRACE_ARGS },
303 { "smallexample", cm_smallexample, NO_BRACE_ARGS },
304 { "smallformat", cm_smallformat, NO_BRACE_ARGS },
305 { "smalllisp", cm_smalllisp, NO_BRACE_ARGS },
306 { "sp", cm_sp, NO_BRACE_ARGS },
307 { "ss", cm_special_char, BRACE_ARGS },
308 { "strong", cm_strong, BRACE_ARGS },
309 { "subheading", cm_subheading, NO_BRACE_ARGS },
310 { "subsection", cm_subsection, NO_BRACE_ARGS },
311 { "subsubheading", cm_subsubheading, NO_BRACE_ARGS },
312 { "subsubsection", cm_subsubsection, NO_BRACE_ARGS },
313 { "subtitle", cm_titlepage_cmds, NO_BRACE_ARGS },
314 { "summarycontents", cm_contents, NO_BRACE_ARGS },
315 { "syncodeindex", cm_synindex, NO_BRACE_ARGS },
316 { "synindex", cm_synindex, NO_BRACE_ARGS },
317 { "t", cm_tt, BRACE_ARGS },
318 { "tab", cm_tab, NO_BRACE_ARGS },
319 { "table", cm_table, NO_BRACE_ARGS },
320 { "tex", cm_tex, NO_BRACE_ARGS },
321 { "tie", cm_tie, BRACE_ARGS },
322 { "tieaccent", cm_accent, MAYBE_BRACE_ARGS },
323 { "tindex", cm_tindex, NO_BRACE_ARGS },
324 { "title", cm_titlepage_cmds, NO_BRACE_ARGS },
325 { "titlefont", cm_titlefont, BRACE_ARGS },
326 { "titlepage", cm_titlepage, NO_BRACE_ARGS },
327 { "today", cm_today, BRACE_ARGS },
328 { "top", cm_top, NO_BRACE_ARGS },
329 { "u", cm_accent, MAYBE_BRACE_ARGS },
330 { "ubaraccent", cm_accent, MAYBE_BRACE_ARGS },
331 { "udotaccent", cm_accent, MAYBE_BRACE_ARGS },
332 { "unmacro", cm_unmacro, NO_BRACE_ARGS },
333 { "unnumbered", cm_unnumbered, NO_BRACE_ARGS },
334 { "unnumberedsec", cm_unnumberedsec, NO_BRACE_ARGS },
335 { "unnumberedsubsec", cm_unnumberedsubsec, NO_BRACE_ARGS },
336 { "unnumberedsubsubsec", cm_unnumberedsubsubsec, NO_BRACE_ARGS },
337 { "uref", cm_uref, BRACE_ARGS },
338 { "url", cm_uref, BRACE_ARGS },
339 { "v", cm_accent, MAYBE_BRACE_ARGS },
340 { "value", cm_value, BRACE_ARGS },
341 { "var", cm_var, BRACE_ARGS },
342 { "verb", cm_verb, NO_BRACE_ARGS },
343 { "verbatim", cm_verbatim, NO_BRACE_ARGS },
344 { "verbatiminclude", cm_verbatiminclude, NO_BRACE_ARGS },
345 { "vindex", cm_vindex, NO_BRACE_ARGS },
346 { "vtable", cm_vtable, NO_BRACE_ARGS },
347 { "vskip", cm_ignore_line, NO_BRACE_ARGS },
348 { "w", cm_w, BRACE_ARGS },
349 { "xml", cm_xml, NO_BRACE_ARGS },
350 { "xref", cm_xref, BRACE_ARGS },
351
352 /* Deprecated commands. These used to be for italics. */
353 { "iappendix", cm_ideprecated, NO_BRACE_ARGS },
354 { "iappendixsec", cm_ideprecated, NO_BRACE_ARGS },
355 { "iappendixsection", cm_ideprecated, NO_BRACE_ARGS },
356 { "iappendixsubsec", cm_ideprecated, NO_BRACE_ARGS },
357 { "iappendixsubsubsec", cm_ideprecated, NO_BRACE_ARGS },
358 { "ichapter", cm_ideprecated, NO_BRACE_ARGS },
359 { "isection", cm_ideprecated, NO_BRACE_ARGS },
360 { "isubsection", cm_ideprecated, NO_BRACE_ARGS },
361 { "isubsubsection", cm_ideprecated, NO_BRACE_ARGS },
362 { "iunnumbered", cm_ideprecated, NO_BRACE_ARGS },
363 { "iunnumberedsec", cm_ideprecated, NO_BRACE_ARGS },
364 { "iunnumberedsubsec", cm_ideprecated, NO_BRACE_ARGS },
365 { "iunnumberedsubsubsec", cm_ideprecated, NO_BRACE_ARGS },
366
367 /* Now @include does what this was used to. */
368 { "infoinclude", cm_obsolete, NO_BRACE_ARGS },
369 { "titlespec", cm_obsolete, NO_BRACE_ARGS },
370
371 { NULL, NULL, NO_BRACE_ARGS }
372 };
373
374 /* The bulk of the Texinfo commands. */
375
376 /* Commands which insert their own names. */
377 void
insert_self(int arg)378 insert_self (int arg)
379 {
380 if (arg == START)
381 add_word (command);
382 }
383
384 void
insert_space(int arg)385 insert_space (int arg)
386 {
387 if (arg == START)
388 {
389 if (xml && !docbook)
390 xml_insert_entity ("space");
391 else
392 add_char (' ');
393 }
394 }
395
396 /* Insert a comma. Useful when a literal , would break our parsing of
397 multiple arguments. */
398 void
cm_comma(int arg)399 cm_comma (int arg)
400 {
401 if (arg == START)
402 add_char (',');
403 }
404
405
406 /* Force a line break in the output. */
407 void
cm_asterisk(void)408 cm_asterisk (void)
409 {
410 if (html)
411 add_word ("<br>");
412 else if (xml && !docbook)
413 xml_insert_entity ("linebreak");
414 else if (docbook)
415 xml_asterisk ();
416 else
417 {
418 close_single_paragraph ();
419 cm_noindent ();
420 }
421 }
422
423 /* Insert ellipsis. */
424 void
cm_dots(int arg)425 cm_dots (int arg)
426 {
427 if (arg == START)
428 {
429 if (xml && !docbook)
430 xml_insert_entity ("dots");
431 else if (docbook)
432 xml_insert_entity ("hellip");
433 else
434 if (html && !in_fixed_width_font)
435 insert_string ("<small class=\"dots\">...</small>");
436 else
437 add_word ("...");
438 }
439 }
440
441 /* Insert ellipsis for sentence end. */
442 void
cm_enddots(int arg)443 cm_enddots (int arg)
444 {
445 if (arg == START)
446 {
447 if (xml && !docbook)
448 xml_insert_entity ("enddots");
449 else if (docbook)
450 {
451 xml_insert_entity ("hellip");
452 add_char ('.');
453 }
454 else
455 if (html && !in_fixed_width_font)
456 insert_string ("<small class=\"enddots\">....</small>");
457 else
458 add_word ("....");
459 }
460 }
461
462 void
cm_bullet(int arg)463 cm_bullet (int arg)
464 {
465 if (arg == START)
466 {
467 if (html)
468 add_word ("•");
469 else if (xml && !docbook)
470 xml_insert_entity ("bullet");
471 else if (docbook)
472 xml_insert_entity ("bull");
473 else
474 add_char ('*');
475 }
476 }
477
478 void
cm_minus(int arg)479 cm_minus (int arg)
480 {
481 if (arg == START)
482 {
483 if (xml)
484 xml_insert_entity ("minus");
485 else if (html)
486 add_word ("−");
487 else
488 add_char ('-');
489 }
490 }
491
492 /* Formatting a dimension unit. */
493 void
cm_dmn(int arg)494 cm_dmn (int arg)
495 {
496 if (html)
497 insert_html_tag_with_attribute (arg, "span", "class=\"dmn\"");
498 else if (docbook)
499 /* No units in docbook yet. */
500 ;
501 else if (xml)
502 xml_insert_element (DIMENSION, arg);
503 }
504
505 /* Insert "TeX". */
506 void
cm_TeX(int arg)507 cm_TeX (int arg)
508 {
509 static int last_position;
510
511 if (arg == START)
512 {
513 if (xml)
514 xml_insert_entity ("tex");
515 else
516 add_word ("TeX");
517
518 last_position = output_paragraph_offset;
519 }
520 else if (last_position != output_paragraph_offset)
521 {
522 warning (_("arguments to @%s ignored"), command);
523 output_paragraph_offset = last_position;
524 }
525 }
526
527 /* Insert "LaTeX". */
528 void
cm_LaTeX(int arg)529 cm_LaTeX (int arg)
530 {
531 static int last_position;
532
533 if (arg == START)
534 {
535 if (xml)
536 xml_insert_entity ("latex");
537 else
538 add_word ("LaTeX");
539
540 last_position = output_paragraph_offset;
541 }
542 else if (last_position != output_paragraph_offset)
543 {
544 warning (_("arguments to @%s ignored"), command);
545 output_paragraph_offset = last_position;
546 }
547 }
548
549 /* Copyright symbol. */
550 void
cm_copyright(int arg)551 cm_copyright (int arg)
552 {
553 if (arg == START)
554 {
555 if (html)
556 add_word ("©");
557 else if (xml && !docbook)
558 xml_insert_entity ("copyright");
559 else if (docbook)
560 xml_insert_entity ("copy");
561 else
562 add_word ("(C)");
563 }
564 }
565
566 /* Registered symbol. */
567 void
cm_registeredsymbol(int arg)568 cm_registeredsymbol (int arg)
569 {
570 if (arg == START)
571 {
572 if (html)
573 add_word ("®");
574 else if (docbook)
575 xml_insert_entity ("reg");
576 else if (xml && !docbook)
577 xml_insert_entity ("registered");
578 else
579 add_word ("(R)");
580 }
581 }
582
583 void
cm_today(int arg)584 cm_today (int arg)
585 {
586 static char *months[12] =
587 { N_("January"), N_("February"), N_("March"), N_("April"), N_("May"),
588 N_("June"), N_("July"), N_("August"), N_("September"), N_("October"),
589 N_("November"), N_("December") };
590 if (arg == START)
591 {
592 time_t timer = time (0);
593 struct tm *ts = localtime (&timer);
594 add_word_args ("%d %s %d", ts->tm_mday, _(months[ts->tm_mon]),
595 ts->tm_year + 1900);
596 }
597 }
598
599 void
cm_comment(void)600 cm_comment (void)
601 {
602 /* For HTML, do not output comments before HTML header is written,
603 otherwise comments before @settitle cause an empty <title> in the
604 header. */
605 if ((html && html_output_head_p) || xml)
606 {
607 char *line;
608 get_rest_of_line (0, &line);
609
610 if (strlen (line) > 0)
611 {
612 int save_inhibit_indentation = inhibit_paragraph_indentation;
613 int save_paragraph_is_open = paragraph_is_open;
614 int save_escape_html = escape_html;
615 int save_xml_no_para = xml_no_para;
616 int i;
617
618 inhibit_paragraph_indentation = 1;
619 escape_html = 0;
620 xml_no_para = 1;
621
622 /* @c and @comment can appear between @item and @itemx,
623 @deffn and @deffnx. */
624 xml_dont_touch_items_defs++;
625
626 /* Use insert for HTML, and XML when indentation is enabled.
627 For Docbook, use add_char. */
628 if (xml && xml_indentation_increment > 0
629 && output_paragraph[output_paragraph_offset-1] != '\n')
630 insert ('\n');
631
632 /* Crunch double hyphens in comments. */
633 add_html_block_elt ("<!-- ");
634 for (i = 0; i < strlen (line); i++)
635 if (line[i] != '-' || (i && line[i-1] != '-'))
636 add_char (line[i]);
637 add_word (" -->");
638
639 if (html)
640 add_char ('\n');
641
642 inhibit_paragraph_indentation = save_inhibit_indentation;
643 paragraph_is_open = save_paragraph_is_open;
644 escape_html = save_escape_html;
645 xml_no_para = save_xml_no_para;
646 xml_dont_touch_items_defs--;
647 }
648
649 free (line);
650 }
651 else
652 cm_ignore_line ();
653 }
654
655
656
657 /* We keep acronyms with two arguments around, to be able to refer to them
658 later with only one argument. */
659 static ACRONYM_DESC *acronyms_stack = NULL;
660
661 static void
cm_acronym_or_abbr(int arg,int is_abbr)662 cm_acronym_or_abbr (int arg, int is_abbr)
663 {
664 char *aa, *description;
665 unsigned len;
666
667 /* We do everything at START. */
668 if (arg == END)
669 return;
670
671 get_until_in_braces (",", &aa);
672 if (input_text[input_text_offset] == ',')
673 input_text_offset++;
674 get_until_in_braces ("}", &description);
675
676 canon_white (aa);
677 canon_white (description);
678
679 /* If not enclosed in braces, strip after comma to be compatible
680 with texinfo.tex. */
681 if (description[0] != '{' && strchr (description, ',') != NULL)
682 {
683 int i = 0;
684 while (description[i] != ',')
685 i++;
686 /* For now, just terminate the string at comma. */
687 description[i] = 0;
688 }
689
690 /* Get description out of braces. */
691 if (description[0] == '{')
692 description++;
693
694 len = strlen (description);
695 if (len && description[len-1] == '}')
696 description[len-1] = 0;
697
698 /* Save new description. */
699 if (strlen (description) > 0)
700 {
701 ACRONYM_DESC *new = xmalloc (sizeof (ACRONYM_DESC));
702
703 new->acronym = xstrdup (aa);
704 new->description = xstrdup (description);
705 new->next = acronyms_stack;
706 acronyms_stack = new;
707 }
708
709 if (html)
710 {
711 add_word (is_abbr ? "<abbr" : "<acronym");
712
713 if (strlen (description) > 0)
714 add_word_args (" title=\"%s\"", text_expansion (description));
715 else if (acronyms_stack)
716 {
717 /* No second argument, get from previous. Search order is from
718 last to first defined, so we get the most recent version of
719 the description. */
720 ACRONYM_DESC *temp = acronyms_stack;
721
722 while (temp)
723 {
724 if (STREQ (aa, temp->acronym)
725 && strlen (temp->description) > 0)
726 {
727 add_word_args (" title=\"%s\"",
728 text_expansion (temp->description));
729 break;
730 }
731 temp = temp->next;
732 }
733 }
734
735 add_char ('>');
736 execute_string ("%s", aa);
737 add_word (is_abbr ? "</abbr>" : "</acronym>");
738 }
739 else if (docbook)
740 {
741 xml_insert_element (is_abbr ? ABBREV : ACRONYM, START);
742 execute_string ("%s", aa);
743 xml_insert_element (is_abbr ? ABBREV : ACRONYM, END);
744 }
745 else if (xml)
746 {
747 xml_insert_element (is_abbr ? ABBREV : ACRONYM, START);
748
749 xml_insert_element (is_abbr ? ABBREVWORD : ACRONYMWORD, START);
750 execute_string ("%s", aa);
751 xml_insert_element (is_abbr ? ABBREVWORD : ACRONYMWORD, END);
752
753 if (strlen (description) > 0)
754 {
755 xml_insert_element (is_abbr ? ABBREVDESC : ACRONYMDESC, START);
756 execute_string ("%s", description);
757 xml_insert_element (is_abbr ? ABBREVDESC : ACRONYMDESC, END);
758 }
759
760 xml_insert_element (is_abbr ? ABBREV : ACRONYM, END);
761 }
762 else
763 execute_string ("%s", aa);
764
765 /* Put description into parenthesis after the acronym for all outputs
766 except XML. */
767 if (strlen (description) > 0 && (!xml || docbook))
768 add_word_args (" (%s)", description);
769 }
770
771 void
cm_acronym(int arg)772 cm_acronym (int arg)
773 {
774 cm_acronym_or_abbr (arg, 0);
775 }
776
777 void
cm_abbr(int arg)778 cm_abbr (int arg)
779 {
780 cm_acronym_or_abbr (arg, 1);
781 }
782
783 void
cm_tt(int arg)784 cm_tt (int arg)
785 {
786 /* @t{} is a no-op in Info. */
787 if (html)
788 insert_html_tag (arg, "tt");
789 else if (xml)
790 xml_insert_element (TT, arg);
791 }
792
793 void
cm_code(int arg)794 cm_code (int arg)
795 {
796 if (arg == START)
797 in_fixed_width_font++;
798
799 if (xml)
800 {
801 if (STREQ (command, "command"))
802 xml_insert_element (COMMAND_TAG, arg);
803 else if (STREQ (command, "env"))
804 xml_insert_element (ENV, arg);
805 else if (STREQ (command, "file"))
806 xml_insert_element (FILE_TAG, arg);
807 else if (STREQ (command, "option"))
808 xml_insert_element (OPTION, arg);
809 else if (STREQ (command, "samp"))
810 {
811 if (docbook && arg == START)
812 {
813 /* Even though @samp is in_fixed_width_font, it
814 should always start a paragraph. Unfortunately,
815 in_fixed_width_font inhibits that. */
816 xml_start_para ();
817 xml_insert_entity ("lsquo");
818 }
819 xml_insert_element (SAMP, arg);
820 if (docbook && arg == END)
821 xml_insert_entity ("rsquo");
822 }
823 else
824 xml_insert_element (CODE, arg);
825 }
826 else if (html)
827 {
828 if (STREQ (command, "code"))
829 insert_html_tag (arg, "code");
830 else
831 { /* Use <samp> tag in general to get typewriter. */
832 if (arg == START)
833 { /* If @samp specifically, add quotes a la TeX output. */
834 if (STREQ (command, "samp")) add_char ('`');
835 add_word ("<samp>");
836 }
837 insert_html_tag_with_attribute (arg, "span", "class=\"%s\"",command);
838 if (arg == END)
839 {
840 add_word ("</samp>");
841 if (STREQ (command, "samp")) add_char ('\'');
842 }
843 }
844 }
845 else
846 {
847 extern int printing_index;
848
849 if (!printing_index)
850 {
851 if (arg == START)
852 add_char ('`');
853 else
854 add_meta_char ('\'');
855 }
856 }
857 }
858
859 void
cm_kbd(int arg)860 cm_kbd (int arg)
861 {
862 if (xml)
863 xml_insert_element (KBD, arg);
864 else if (html)
865 { /* Seems like we should increment in_fixed_width_font for Info
866 format too, but then the quote-omitting special case gets
867 confused. Punt. */
868 if (arg == START)
869 in_fixed_width_font++;
870 insert_html_tag (arg, "kbd");
871 }
872 else
873 { /* People use @kbd in an example to get the "user input" font.
874 We don't want quotes in that case. */
875 if (!in_fixed_width_font)
876 cm_code (arg);
877 }
878 }
879
880 /* Just show a url (http://example.org/..., for example), don't link to it. */
881 void
cm_indicate_url(int arg,int start,int end)882 cm_indicate_url (int arg, int start, int end)
883 {
884 if (xml)
885 xml_insert_element (URL, arg);
886 else if (html)
887 {
888 if (arg == START)
889 add_word ("<");
890 insert_html_tag (arg, "code");
891 if (arg != START)
892 add_word (">");
893 }
894 else
895 if (arg == START)
896 add_word ("<");
897 else
898 add_word (">");
899 }
900
901 void
cm_key(int arg)902 cm_key (int arg)
903 {
904 if (xml)
905 xml_insert_element (KEY, arg);
906 else if (html)
907 add_word (arg == START ? "<" : ">");
908 else
909 add_char (arg == START ? '<' : '>');
910 }
911
912 /* Handle a command that switches to a non-fixed-width font. */
913 void
not_fixed_width(int arg)914 not_fixed_width (int arg)
915 {
916 if (arg == START)
917 in_fixed_width_font = 0;
918 }
919
920 /* @var in makeinfo just uppercases the text. */
921 void
cm_var(int arg,int start_pos,int end_pos)922 cm_var (int arg, int start_pos, int end_pos)
923 {
924 if (xml)
925 xml_insert_element (VAR, arg);
926 else
927 {
928 not_fixed_width (arg);
929
930 if (html)
931 insert_html_tag (arg, "var");
932 else if (arg == END)
933 {
934 while (start_pos < end_pos)
935 {
936 unsigned char c = output_paragraph[start_pos];
937 if (strchr ("[](),", c))
938 warning (_("unlikely character %c in @var"), c);
939 output_paragraph[start_pos] = coerce_to_upper (c);
940 start_pos++;
941 }
942 }
943 }
944 }
945
946 void
cm_sc(int arg,int start_pos,int end_pos)947 cm_sc (int arg, int start_pos, int end_pos)
948 {
949 if (xml)
950 xml_insert_element (SC, arg);
951 else
952 {
953 not_fixed_width (arg);
954
955 if (arg == START)
956 {
957 if (html)
958 insert_html_tag_with_attribute (arg, "span", "class=\"sc\"");
959 }
960 else
961 {
962 int all_upper;
963
964 if (html)
965 start_pos += sizeof ("<span class=\"sc\">") - 1; /* skip <span> */
966
967 /* Avoid the warning below if there's no text inside @sc{}, or
968 when processing menus under --no-headers. */
969 all_upper = start_pos < end_pos;
970
971 while (start_pos < end_pos)
972 {
973 unsigned char c = output_paragraph[start_pos];
974 if (!isupper (c))
975 all_upper = 0;
976 if (!html)
977 output_paragraph[start_pos] = coerce_to_upper (c);
978 start_pos++;
979 }
980 if (all_upper)
981 warning (_("@sc argument all uppercase, thus no effect"));
982
983 if (html)
984 insert_html_tag (arg, "span");
985 }
986 }
987 }
988
989 void
cm_dfn(int arg,int position)990 cm_dfn (int arg, int position)
991 {
992 if (xml)
993 xml_insert_element (DFN, arg);
994 else
995 {
996 if (html)
997 insert_html_tag (arg, "dfn");
998 else if (arg == START)
999 add_char ('"');
1000 else
1001 add_meta_char ('"');
1002 }
1003 }
1004
1005 void
cm_emph(int arg)1006 cm_emph (int arg)
1007 {
1008 if (xml)
1009 xml_insert_element (EMPH, arg);
1010 else if (html)
1011 insert_html_tag (arg, "em");
1012 else
1013 add_char ('_');
1014 }
1015
1016 void
cm_verb(int arg)1017 cm_verb (int arg)
1018 {
1019 int character;
1020 int delimiter = 0; /* avoid warning */
1021 int seen_end = 0;
1022
1023 in_fixed_width_font++;
1024 /* are these necessary ? */
1025 last_char_was_newline = 0;
1026
1027 if (html)
1028 add_word ("<tt>");
1029
1030 if (input_text_offset < input_text_length)
1031 {
1032 character = curchar ();
1033 if (character == '{')
1034 input_text_offset++;
1035 else
1036 line_error (_("`{' expected, but saw `%c'"), character);
1037 }
1038
1039 if (input_text_offset < input_text_length)
1040 {
1041 delimiter = curchar ();
1042 input_text_offset++;
1043 }
1044
1045 while (input_text_offset < input_text_length)
1046 {
1047 character = curchar ();
1048
1049 if (character == '\n')
1050 {
1051 line_number++;
1052 if (html)
1053 add_word ("<br>\n");
1054 }
1055
1056 else if (html && character == '<')
1057 add_word ("<");
1058
1059 else if (html && character == '&')
1060 add_word ("&");
1061
1062 else if (character == delimiter && input_text[input_text_offset+1] == '}')
1063 { /* Assume no newlines in END_VERBATIM. */
1064 seen_end = 1;
1065 input_text_offset++;
1066 break;
1067 }
1068
1069 else
1070 add_char (character);
1071
1072 input_text_offset++;
1073 }
1074
1075 if (!seen_end)
1076 warning (_("end of file inside verb block"));
1077
1078 if (input_text_offset < input_text_length)
1079 {
1080 character = curchar ();
1081 if (character == '}')
1082 input_text_offset++;
1083 else
1084 line_error (_("`}' expected, but saw `%c'"), character);
1085 }
1086
1087 if (html)
1088 add_word ("</tt>");
1089
1090 in_fixed_width_font--;
1091 }
1092
1093
1094 void
cm_strong(int arg,int start_pos,int end_pos)1095 cm_strong (int arg, int start_pos, int end_pos)
1096 {
1097 if (docbook && arg == START)
1098 xml_insert_element_with_attribute (B, arg, "role=\"bold\"");
1099 else if (xml)
1100 xml_insert_element (STRONG, arg);
1101 else if (html)
1102 insert_html_tag (arg, "strong");
1103 else
1104 add_char ('*');
1105
1106 if (!xml && !html && !docbook && !no_headers
1107 && arg == END
1108 && end_pos - start_pos >= 6
1109 && (STRNCASEEQ ((char *) output_paragraph + start_pos, "*Note:", 6)
1110 || STRNCASEEQ ((char *) output_paragraph + start_pos, "*Note ", 6)))
1111 {
1112 /* Translators: "Note:" is literal here and should not be
1113 translated. @strong{Nota}, say, does not cause the problem. */
1114 warning (_("@strong{Note...} produces a spurious cross-reference in Info; reword to avoid that"));
1115 /* Adjust the output to avoid writing the bad xref. */
1116 output_paragraph[start_pos + 5] = '_';
1117 }
1118 }
1119
1120 void
cm_cite(int arg,int position)1121 cm_cite (int arg, int position)
1122 {
1123 if (xml)
1124 xml_insert_element (CITE, arg);
1125 else if (html)
1126 insert_html_tag (arg, "cite");
1127 else
1128 {
1129 if (arg == START)
1130 add_char ('`');
1131 else
1132 add_char ('\'');
1133 }
1134 }
1135
1136 /* No highlighting, but argument switches fonts. */
1137 void
cm_not_fixed_width(int arg,int start,int end)1138 cm_not_fixed_width (int arg, int start, int end)
1139 {
1140 if (xml)
1141 xml_insert_element (NOTFIXEDWIDTH, arg);
1142 not_fixed_width (arg);
1143 }
1144
1145 void
cm_i(int arg)1146 cm_i (int arg)
1147 {
1148 /* Make use of <lineannotation> of Docbook, if we are
1149 inside an @example or similar. */
1150 extern int printing_index;
1151 if (docbook && !filling_enabled && !printing_index)
1152 xml_insert_element (LINEANNOTATION, arg);
1153 else if (xml)
1154 xml_insert_element (I, arg);
1155 else if (html)
1156 insert_html_tag (arg, "i");
1157 else
1158 not_fixed_width (arg);
1159 }
1160
1161 void
cm_slanted(int arg)1162 cm_slanted (int arg)
1163 {
1164 /* Make use of <lineannotation> of Docbook, if we are
1165 inside an @example or similar. */
1166 extern int printing_index;
1167 if (docbook && !filling_enabled && !printing_index)
1168 xml_insert_element (LINEANNOTATION, arg);
1169 else if (xml)
1170 xml_insert_element (SLANTED, arg);
1171 else if (html)
1172 insert_html_tag (arg, "i");
1173 else
1174 not_fixed_width (arg);
1175 }
1176
1177 void
cm_b(int arg)1178 cm_b (int arg)
1179 {
1180 /* See cm_i comments. */
1181 extern int printing_index;
1182 if (docbook && !filling_enabled && !printing_index)
1183 xml_insert_element (LINEANNOTATION, arg);
1184 else if (docbook && arg == START)
1185 xml_insert_element_with_attribute (B, arg, "role=\"bold\"");
1186 else if (xml)
1187 xml_insert_element (B, arg);
1188 else if (html)
1189 insert_html_tag (arg, "b");
1190 else
1191 not_fixed_width (arg);
1192 }
1193
1194 void
cm_r(int arg)1195 cm_r (int arg)
1196 {
1197 /* See cm_i comments. */
1198 extern int printing_index;
1199 if (docbook && !filling_enabled && !printing_index)
1200 xml_insert_element (LINEANNOTATION, arg);
1201 else if (xml)
1202 xml_insert_element (R, arg);
1203 else if (html)
1204 insert_html_tag_with_attribute (arg, "span", "class=\"roman\"");
1205 else
1206 not_fixed_width (arg);
1207 }
1208
1209 void
cm_sansserif(int arg)1210 cm_sansserif (int arg)
1211 {
1212 /* See cm_i comments. */
1213 extern int printing_index;
1214 if (docbook && !filling_enabled && !printing_index)
1215 xml_insert_element (LINEANNOTATION, arg);
1216 else if (xml)
1217 xml_insert_element (SANSSERIF, arg);
1218 else if (html)
1219 insert_html_tag_with_attribute (arg, "span", "class=\"sansserif\"");
1220 else
1221 not_fixed_width (arg);
1222 }
1223
1224 void
cm_titlefont(int arg)1225 cm_titlefont (int arg)
1226 {
1227 if (xml)
1228 xml_insert_element (TITLEFONT, arg);
1229 else
1230 {
1231 not_fixed_width (arg);
1232 if (html)
1233 {
1234 html_title_written = 1; /* suppress title from @settitle */
1235 if (arg == START)
1236 add_word ("<h1 class=\"titlefont\">");
1237 else
1238 add_word ("</h1>\n");
1239 }
1240 }
1241 }
1242
1243
1244 /* Unfortunately, we cannot interpret @math{} contents like TeX does. We just
1245 pass them through. */
1246 void
cm_math(int arg)1247 cm_math (int arg)
1248 {
1249 if (xml && !docbook)
1250 xml_insert_element (MATH, arg);
1251 }
1252
1253 /* Various commands are no-op's. */
1254 void
cm_no_op(void)1255 cm_no_op (void)
1256 {
1257 }
1258
1259
1260 /* For proofing single chapters, etc. */
1261 void
cm_novalidate(void)1262 cm_novalidate (void)
1263 {
1264 validating = 0;
1265 }
1266
1267
1268 /* Prevent the argument from being split across two lines. */
1269 void
cm_w(int arg)1270 cm_w (int arg)
1271 {
1272 if (arg == START)
1273 non_splitting_words++;
1274 else
1275 {
1276 if (docbook || html || xml)
1277 /* This is so @w{$}Log$ doesn't end up as <dollar>Log<dollar>
1278 in the output. */
1279 insert_string ("<!-- /@w -->");
1280
1281 non_splitting_words--;
1282 }
1283 }
1284
1285
1286 /* An unbreakable word space. Same as @w{ } for makeinfo, but different
1287 for TeX (the space stretches and stretches, and does not inhibit
1288 hyphenation). */
1289 void
cm_tie(int arg)1290 cm_tie (int arg)
1291 {
1292 if (arg == START)
1293 {
1294 cm_w (START);
1295 add_char (' ');
1296 }
1297 else
1298 cm_w (END);
1299 }
1300
1301 /* Explain that this command is obsolete, thus the user shouldn't
1302 do anything with it. */
1303 static void
cm_obsolete(int arg,int start,int end)1304 cm_obsolete (int arg, int start, int end)
1305 {
1306 if (arg == START)
1307 warning (_("%c%s is obsolete"), COMMAND_PREFIX, command);
1308 }
1309
1310
1311 /* Inhibit the indentation of the next paragraph, but not of following
1312 paragraphs. */
1313 void
cm_noindent(void)1314 cm_noindent (void)
1315 {
1316 if (!inhibit_paragraph_indentation)
1317 inhibit_paragraph_indentation = -1;
1318 }
1319
1320 void
cm_noindent_cmd(void)1321 cm_noindent_cmd (void)
1322 {
1323 cm_noindent ();
1324 xml_no_indent = 1;
1325 skip_whitespace_and_newlines();
1326
1327 if (xml)
1328 xml_start_para ();
1329 else if (html && !paragraph_is_open)
1330 add_html_block_elt ("<p class=\"noindent\">");
1331 else
1332 {
1333 paragraph_is_open = 0;
1334 start_paragraph ();
1335 }
1336 }
1337
1338 /* Force indentation of the next paragraph. */
1339 void
cm_indent(void)1340 cm_indent (void)
1341 {
1342 inhibit_paragraph_indentation = 0;
1343 xml_no_indent = 0;
1344 skip_whitespace_and_newlines();
1345
1346 if (xml)
1347 xml_start_para ();
1348 else if (html && !paragraph_is_open)
1349 add_html_block_elt ("<p class=\"indent\">");
1350 else
1351 start_paragraph ();
1352 }
1353
1354 /* I don't know exactly what to do with this. Should I allow
1355 someone to switch filenames in the middle of output? Since the
1356 file could be partially written, this doesn't seem to make sense.
1357 Another option: ignore it, since they don't really want to
1358 switch files. Finally, complain, or at least warn. It doesn't
1359 really matter, anyway, since this doesn't get executed. */
1360 void
cm_setfilename(void)1361 cm_setfilename (void)
1362 {
1363 char *filename;
1364 get_rest_of_line (1, &filename);
1365 /* warning ("`@%s %s' encountered and ignored", command, filename); */
1366 if (xml)
1367 add_word_args ("<setfilename>%s</setfilename>", filename);
1368 free (filename);
1369 }
1370
1371 void
cm_settitle(void)1372 cm_settitle (void)
1373 {
1374 if (xml)
1375 {
1376 xml_begin_document (current_output_filename);
1377 xml_insert_element (SETTITLE, START);
1378 xml_in_book_title = 1;
1379 get_rest_of_line (0, &title);
1380 execute_string ("%s", title);
1381 xml_in_book_title = 0;
1382 xml_insert_element (SETTITLE, END);
1383 }
1384 else
1385 get_rest_of_line (0, &title);
1386 }
1387
1388
1389 /* Ignore argument in braces. */
1390 void
cm_ignore_arg(int arg,int start_pos,int end_pos)1391 cm_ignore_arg (int arg, int start_pos, int end_pos)
1392 {
1393 if (arg == END)
1394 output_paragraph_offset = start_pos;
1395 }
1396
1397 /* Ignore argument on rest of line. */
1398 void
cm_ignore_line(void)1399 cm_ignore_line (void)
1400 {
1401 discard_until ("\n");
1402 }
1403
1404 /* Insert the number of blank lines passed as argument. */
1405 void
cm_sp(void)1406 cm_sp (void)
1407 {
1408 int lines;
1409 char *line;
1410
1411 /* Due to tricky stuff in execute_string(), @value{} can't be expanded.
1412 So there is really no reason to enable expansion for @sp parameters. */
1413 get_rest_of_line (0, &line);
1414
1415 if (sscanf (line, "%d", &lines) != 1 || lines <= 0)
1416 line_error (_("@sp requires a positive numeric argument, not `%s'"), line);
1417 else
1418 {
1419 if (xml)
1420 {
1421 /* @sp can appear between @item and @itemx, @deffn and @deffnx. */
1422 xml_dont_touch_items_defs++;
1423 xml_insert_element_with_attribute (SP, START, "lines=\"%s\"", line);
1424 /* insert_string (line);*/
1425 xml_insert_element (SP, END);
1426 xml_dont_touch_items_defs--;
1427 }
1428 else
1429 {
1430 /* Must disable filling since otherwise multiple newlines is like
1431 multiple spaces. Must close paragraph since that's what the
1432 manual says and that's what TeX does. */
1433 int save_filling_enabled = filling_enabled;
1434 filling_enabled = 0;
1435
1436 /* close_paragraph generates an extra blank line. */
1437 close_single_paragraph ();
1438
1439 if (lines && html && !executing_string)
1440 html_output_head ();
1441
1442 if (html)
1443 add_html_block_elt ("<pre class=\"sp\">\n");
1444
1445 while (lines--)
1446 add_char ('\n');
1447
1448 if (html)
1449 add_html_block_elt ("</pre>\n");
1450
1451 filling_enabled = save_filling_enabled;
1452 }
1453 }
1454 free (line);
1455 }
1456
1457 /* @dircategory LINE outputs INFO-DIR-SECTION LINE, unless --no-headers. */
1458 void
cm_dircategory(void)1459 cm_dircategory (void)
1460 {
1461 char *line;
1462
1463 if (html || docbook)
1464 cm_ignore_line ();
1465 else if (xml)
1466 {
1467 xml_insert_element (DIRCATEGORY, START);
1468 get_rest_of_line (1, &line);
1469 insert_string (line);
1470 free (line);
1471 xml_insert_element (DIRCATEGORY, END);
1472 }
1473 else
1474 {
1475 get_rest_of_line (1, &line);
1476
1477 if (!no_headers && !html)
1478 {
1479 kill_self_indent (-1); /* make sure there's no indentation */
1480 insert_string ("INFO-DIR-SECTION ");
1481 insert_string (line);
1482 insert ('\n');
1483 }
1484
1485 free (line);
1486 }
1487 }
1488
1489 /* Start a new line with just this text on it.
1490 Then center the line of text.
1491 */
1492 void
cm_center(void)1493 cm_center (void)
1494 {
1495 if (xml)
1496 {
1497 char *line;
1498 xml_insert_element (CENTER, START);
1499 get_rest_of_line (0, &line);
1500 execute_string ("%s", line);
1501 free (line);
1502 xml_insert_element (CENTER, END);
1503 }
1504 else
1505 {
1506 int i, start, length;
1507 char *line;
1508 int save_indented_fill = indented_fill;
1509 int save_filling_enabled = filling_enabled;
1510 int fudge_factor = 1;
1511
1512 filling_enabled = indented_fill = 0;
1513 cm_noindent ();
1514 start = output_paragraph_offset;
1515
1516 if (html)
1517 add_html_block_elt ("<div align=\"center\">");
1518
1519 inhibit_output_flushing ();
1520 get_rest_of_line (0, &line);
1521 execute_string ("%s", line);
1522 free (line);
1523 uninhibit_output_flushing ();
1524 if (html)
1525 add_html_block_elt ("</div>");
1526
1527 else
1528 {
1529 i = output_paragraph_offset - 1;
1530 while (i > (start - 1) && output_paragraph[i] == '\n')
1531 i--;
1532
1533 output_paragraph_offset = ++i;
1534 length = output_paragraph_offset - start;
1535
1536 if (length < (fill_column - fudge_factor))
1537 {
1538 line = xmalloc (1 + length);
1539 memcpy (line, (char *)(output_paragraph + start), length);
1540
1541 i = (fill_column - fudge_factor - length) / 2;
1542 output_paragraph_offset = start;
1543
1544 while (i--)
1545 insert (' ');
1546
1547 for (i = 0; i < length; i++)
1548 insert (line[i]);
1549
1550 free (line);
1551 }
1552 }
1553
1554 insert ('\n');
1555 filling_enabled = save_filling_enabled;
1556 indented_fill = save_indented_fill;
1557 close_single_paragraph ();
1558 if (looking_at("\n"))
1559 insert ('\n');
1560 }
1561 }
1562
1563 /* Show what an expression returns. */
1564 void
cm_result(int arg)1565 cm_result (int arg)
1566 {
1567 if (arg == END)
1568 add_word (html ? "=>" : "=>");
1569 }
1570
1571 /* What an expression expands to. */
1572 void
cm_expansion(int arg)1573 cm_expansion (int arg)
1574 {
1575 if (arg == END)
1576 add_word (html ? "==>" : "==>");
1577 }
1578
1579 /* Indicates two expressions are equivalent. */
1580 void
cm_equiv(int arg)1581 cm_equiv (int arg)
1582 {
1583 if (arg == END)
1584 add_word ("==");
1585 }
1586
1587 /* What an expression may print. */
1588 void
cm_print(int arg)1589 cm_print (int arg)
1590 {
1591 if (arg == END)
1592 add_word ("-|");
1593 }
1594
1595 /* An error signaled. */
1596 void
cm_error(int arg)1597 cm_error (int arg)
1598 {
1599 if (arg == END)
1600 add_word (html ? "error-->" : "error-->");
1601 }
1602
1603 /* The location of point in an example of a buffer. */
1604 void
cm_point(int arg)1605 cm_point (int arg)
1606 {
1607 if (arg == END)
1608 add_word ("-!-");
1609 }
1610
1611 /* @exdent: Start a new line with just this text on it.
1612 The text is outdented one level if possible. */
1613 void
cm_exdent(void)1614 cm_exdent (void)
1615 {
1616 char *line;
1617 int save_indent = current_indent;
1618 int save_in_fixed_width_font = in_fixed_width_font;
1619
1620 /* Read argument. */
1621 get_rest_of_line (0, &line);
1622
1623 /* Exdent the output. Actually this may be a no-op. */
1624 if (current_indent)
1625 current_indent -= default_indentation_increment;
1626
1627 /* @exdent arg is supposed to be in roman. */
1628 in_fixed_width_font = 0;
1629
1630 /* The preceding newline already inserted the `current_indent'.
1631 Remove one level's worth. */
1632 kill_self_indent (default_indentation_increment);
1633
1634 if (html)
1635 add_word ("<br>");
1636 else if (docbook)
1637 xml_insert_element (LINEANNOTATION, START);
1638 else if (xml)
1639 xml_insert_element (EXDENT, START);
1640
1641 /* Can't close_single_paragraph, then we lose preceding blank lines. */
1642 flush_output ();
1643 execute_string ("%s", line);
1644 free (line);
1645
1646 if (html)
1647 add_word ("<br>");
1648 else if (xml)
1649 {
1650 xml_insert_element (docbook ? LINEANNOTATION : EXDENT, END);
1651 insert ('\n');
1652 }
1653
1654 close_single_paragraph ();
1655
1656 current_indent = save_indent;
1657 in_fixed_width_font = save_in_fixed_width_font;
1658 if (!xml)
1659 start_paragraph ();
1660 }
1661
1662 /*
1663 Read include-filename, process the include-file:
1664 verbatim_include == 0: process through reader_loop
1665 verbatim_include != 0: process through handle_verbatim_environment
1666 */
1667 static void
handle_include(int verbatim_include)1668 handle_include (int verbatim_include)
1669 {
1670 char *arg, *filename;
1671
1672 if (macro_expansion_output_stream && !executing_string)
1673 me_append_before_this_command ();
1674
1675 if (!insertion_stack)
1676 close_paragraph (); /* No blank lines etc. if not at outer level. */
1677
1678 get_rest_of_line (0, &arg);
1679 /* We really only want to expand @value, but it's easier to just do
1680 everything. TeX will only work with @value. */
1681 filename = text_expansion (arg);
1682 free (arg);
1683
1684 if (macro_expansion_output_stream && !executing_string)
1685 remember_itext (input_text, input_text_offset);
1686
1687 pushfile ();
1688
1689 /* In verbose mode we print info about including another file. */
1690 if (verbose_mode)
1691 {
1692 int i = 0;
1693 FSTACK *stack = filestack;
1694
1695 for (i = 0, stack = filestack; stack; stack = stack->next, i++);
1696
1697 i *= 2;
1698
1699 printf ("%*s", i, "");
1700 printf ("%c%s `%s'\n", COMMAND_PREFIX, command, filename);
1701 fflush (stdout);
1702 }
1703
1704 if (!find_and_load (filename, 1))
1705 {
1706 popfile ();
1707 line_number--;
1708
1709 /* /wh/bar:5: @include/@verbatiminclude `foo': No such file or dir */
1710 line_error ("%c%s `%s': %s", COMMAND_PREFIX, command, filename,
1711 strerror (errno));
1712
1713 free (filename);
1714 return;
1715 }
1716 else
1717 {
1718 if (macro_expansion_output_stream && !executing_string)
1719 remember_itext (input_text, input_text_offset);
1720
1721 if (!verbatim_include)
1722 reader_loop ();
1723 else
1724 handle_verbatim_environment (0);
1725 }
1726 free (filename);
1727 popfile ();
1728 }
1729
1730
1731 /* Include file as if put in @verbatim environment */
1732 void
cm_verbatiminclude(void)1733 cm_verbatiminclude (void)
1734 {
1735 handle_include (1);
1736 }
1737
1738
1739 /* Remember this file, and move onto the next. */
1740 void
cm_include(void)1741 cm_include (void)
1742 {
1743 handle_include (0);
1744 }
1745
1746
1747 /* @bye: Signals end of processing. Easy to make this happen. */
1748
1749 void
cm_bye(void)1750 cm_bye (void)
1751 {
1752 discard_braces (); /* should not have any unclosed braces left */
1753 input_text_offset = input_text_length;
1754 }
1755
1756 /* @paragraphindent */
1757
1758 static void
cm_paragraphindent(void)1759 cm_paragraphindent (void)
1760 {
1761 char *arg;
1762
1763 get_rest_of_line (1, &arg);
1764 if (set_paragraph_indent (arg) != 0)
1765 line_error (_("Bad argument to %c%s"), COMMAND_PREFIX, command);
1766
1767 free (arg);
1768 }
1769
1770
1771 /* @exampleindent: change indentation of example-like environments. */
1772 static int
set_example_indentation_increment(char * string)1773 set_example_indentation_increment (char *string)
1774 {
1775 if (strcmp (string, "asis") == 0 || strcmp (string, _("asis")) == 0)
1776 ;
1777 else if (strcmp (string, "none") == 0 || strcmp (string, _("none")) == 0)
1778 example_indentation_increment = 0;
1779 else if (sscanf (string, "%d", &example_indentation_increment) != 1)
1780 return -1;
1781 return 0;
1782 }
1783
1784 static void
cm_exampleindent(void)1785 cm_exampleindent (void)
1786 {
1787 char *arg;
1788
1789 get_rest_of_line (1, &arg);
1790 if (set_example_indentation_increment (arg) != 0)
1791 line_error (_("Bad argument to @%s"), command);
1792
1793 if (input_text[input_text_offset] == '\n')
1794 close_single_paragraph ();
1795
1796 free (arg);
1797 }
1798
1799
1800 /* @firstparagraphindent: suppress indentation in first paragraphs after
1801 headings. */
1802 static int
set_firstparagraphindent(char * string)1803 set_firstparagraphindent (char *string)
1804 {
1805 if (STREQ (string, "insert") || STREQ (string, _("insert")))
1806 do_first_par_indent = 1;
1807 else if (STREQ (string, "none") || STREQ (string, _("none")))
1808 do_first_par_indent = 0;
1809 else
1810 return -1;
1811 return 0;
1812 }
1813
1814 static void
cm_firstparagraphindent(void)1815 cm_firstparagraphindent (void)
1816 {
1817 char *arg;
1818
1819 get_rest_of_line (1, &arg);
1820 if (set_firstparagraphindent (arg) != 0)
1821 line_error (_("Bad argument to %c%s"), COMMAND_PREFIX, command);
1822
1823 free (arg);
1824 }
1825
1826 /* For DocBook and XML, produce . for `.@:'. This gives the processing
1827 software a fighting chance to treat it specially by not adding extra space.
1828
1829 Do this also for ?, !, and :. */
1830 void
cm_colon(void)1831 cm_colon (void)
1832 {
1833 if (xml)
1834 {
1835 if (strchr (".?!:", input_text[input_text_offset-3]) != NULL)
1836 {
1837 /* Erase literal character that's there, except `>', which is
1838 part of the XML tag. */
1839 if (output_paragraph[output_paragraph_offset-1] != '>')
1840 output_paragraph_offset--;
1841
1842 switch (input_text[input_text_offset-3])
1843 {
1844 case '.':
1845 xml_insert_entity ("period");
1846 break;
1847 case '?':
1848 xml_insert_entity ("quest");
1849 break;
1850 case '!':
1851 xml_insert_entity ("excl");
1852 break;
1853 case ':':
1854 xml_insert_entity ("colon");
1855 break;
1856 }
1857 }
1858 }
1859 }
1860
1861 /* Ending sentences explicitly. Currently, only outputs entities for XML
1862 output, for other formats it calls insert_self. */
1863 void
cm_punct(int arg)1864 cm_punct (int arg)
1865 {
1866 if (xml && !docbook)
1867 {
1868 switch (input_text[input_text_offset-1])
1869 {
1870 case '.':
1871 xml_insert_entity ("eosperiod");
1872 break;
1873 case '?':
1874 xml_insert_entity ("eosquest");
1875 break;
1876 case '!':
1877 xml_insert_entity ("eosexcl");
1878 break;
1879 }
1880 }
1881 else
1882 {
1883 insert_self (arg);
1884 }
1885 }
1886