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 ("&bull;");
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 ("&minus;");
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 ("&copy;");
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 ("&reg;");
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 ("&lt;");
890       insert_html_tag (arg, "code");
891       if (arg != START)
892         add_word ("&gt;");
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 ? "&lt;" : "&gt;");
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 ("&lt;");
1058 
1059       else if (html && character == '&')
1060         add_word ("&amp;");
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 ? "=&gt;" : "=>");
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 ? "==&gt;" : "==>");
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--&gt;" : "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 &period; 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