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