de-errno
[dragonfly.git] / contrib / texinfo / makeinfo / cmds.c
1 /* cmds.c -- Texinfo commands.
2    $Id: cmds.c,v 1.79 2002/03/28 16:35:29 karl Exp $
3
4    Copyright (C) 1998, 99, 2000, 01, 02 Free Software Foundation, Inc.
5
6    This program is free software; you can redistribute it and/or modify
7    it under the terms of the GNU General Public License as published by
8    the Free Software Foundation; either version 2, or (at your option)
9    any later version.
10
11    This program is distributed in the hope that it will be useful,
12    but WITHOUT ANY WARRANTY; without even the implied warranty of
13    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14    GNU General Public License for more details.
15
16    You should have received a copy of the GNU General Public License
17    along with this program; if not, write to the Free Software Foundation,
18    Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */
19
20 #include "system.h"
21 #include "cmds.h"
22 #include "defun.h"
23 #include "files.h"
24 #include "footnote.h"
25 #include "insertion.h"
26 #include "lang.h"
27 #include "macro.h"
28 #include "makeinfo.h"
29 #include "node.h"
30 #include "sectioning.h"
31 #include "toc.h"
32 #include "xml.h"
33
34 #ifdef TM_IN_SYS_TIME
35 #include <sys/time.h>
36 #else
37 #include <time.h>
38 #endif
39
40
41 void insert_self (), insert_space (), cm_ignore_line (), cm_ignore_arg ();
42
43 void
44   cm_TeX (), cm_acronym (), cm_asterisk (), cm_b (), cm_bullet (), cm_cite (),
45   cm_code (), cm_copyright (), cm_ctrl (), cm_dfn (), cm_dircategory (),
46   cm_direntry (), cm_dmn (), cm_dots (), cm_emph (), cm_enddots (), cm_i (),
47   cm_image (), cm_kbd (), cm_key (), cm_no_op (), 
48   cm_novalidate (), cm_not_fixed_width (), cm_r (),
49   cm_strong (), cm_var (), cm_sc (), cm_w (), cm_email (), cm_url (),
50   cm_verb (), cm_copying (), cm_insert_copying (),
51   cm_documentdescription ();
52
53 void
54   cm_anchor (), cm_node (), cm_menu (), cm_xref (), cm_ftable (),
55   cm_vtable (), cm_pxref (), cm_inforef (), cm_uref (), cm_email (),
56   cm_quotation (), cm_display (), cm_smalldisplay (), cm_itemize (),
57   cm_enumerate (), cm_tab (), cm_table (), cm_itemx (), cm_noindent (),
58   cm_setfilename (), cm_br (), cm_sp (), cm_page (), cm_group (),
59   cm_center (), cm_ref (), cm_include (), cm_bye (), cm_item (), cm_end (),
60   cm_kindex (), cm_cindex (), cm_findex (), cm_pindex (), cm_vindex (),
61   cm_tindex (), cm_synindex (), cm_printindex (), cm_minus (),
62   cm_example (), cm_smallexample (), cm_smalllisp (), cm_lisp (),
63   cm_format (), cm_smallformat (), cm_exdent (), cm_defindex (),
64   cm_defcodeindex (), cm_result (), cm_expansion (), cm_equiv (),
65   cm_print (), cm_error (), cm_point (), cm_today (), cm_flushleft (),
66   cm_flushright (), cm_finalout (), cm_cartouche (), cm_detailmenu (),
67   cm_multitable (), cm_settitle (), cm_titlefont (), cm_tt (),
68   cm_verbatim (), cm_verbatiminclude ();
69
70 /* Conditionals. */
71 void cm_set (), cm_clear (), cm_ifset (), cm_ifclear ();
72 void cm_value (), cm_ifeq ();
73
74 /* Options. */
75 static void cm_paragraphindent (), cm_exampleindent ();
76
77 /* Internals. */
78 static void cm_obsolete ();
79
80 /* A random string.  */
81 static const char small_tag[] = "small";
82
83 /* The dispatch table.  */
84 COMMAND command_table[] = {
85   { "\t", insert_space, NO_BRACE_ARGS },
86   { "\n", insert_space, NO_BRACE_ARGS },
87   { " ", insert_space, NO_BRACE_ARGS },
88   { "!", insert_self, NO_BRACE_ARGS },
89   { "\"", cm_accent_umlaut, MAYBE_BRACE_ARGS },
90   { "'", cm_accent_acute, MAYBE_BRACE_ARGS },
91   { "*", cm_asterisk, NO_BRACE_ARGS },
92   { ",", cm_accent_cedilla, MAYBE_BRACE_ARGS },
93   { "-", cm_no_op, NO_BRACE_ARGS },
94   { ".", insert_self, NO_BRACE_ARGS },
95   { ":", cm_no_op, NO_BRACE_ARGS },
96   { "=", cm_accent, MAYBE_BRACE_ARGS },
97   { "?", insert_self, NO_BRACE_ARGS },
98   { "@", insert_self, NO_BRACE_ARGS },
99   { "\\", insert_self, NO_BRACE_ARGS },
100   { "^", cm_accent_hat, MAYBE_BRACE_ARGS },
101   { "`", cm_accent_grave, MAYBE_BRACE_ARGS },
102   { "{", insert_self, NO_BRACE_ARGS },
103   { "|", cm_no_op, NO_BRACE_ARGS },
104   { "}", insert_self, NO_BRACE_ARGS },
105   { "~", cm_accent_tilde, MAYBE_BRACE_ARGS },
106   { "AA", cm_special_char, BRACE_ARGS },
107   { "AE", cm_special_char, BRACE_ARGS },
108   { "H", cm_accent, MAYBE_BRACE_ARGS },
109   { "L", cm_special_char, BRACE_ARGS },
110   { "O", cm_special_char, BRACE_ARGS },
111   { "OE", cm_special_char, BRACE_ARGS },
112   { "TeX", cm_TeX, BRACE_ARGS },
113   { "aa", cm_special_char, BRACE_ARGS },
114   { "acronym", cm_acronym, BRACE_ARGS },
115   { "ae", cm_special_char, BRACE_ARGS },
116   { "afivepaper", cm_ignore_line, NO_BRACE_ARGS },
117   { "afourlatex", cm_ignore_line, NO_BRACE_ARGS },
118   { "afourpaper", cm_ignore_line, NO_BRACE_ARGS },
119   { "afourwide", cm_ignore_line, NO_BRACE_ARGS },
120   { "alias", cm_alias, NO_BRACE_ARGS },
121   { "anchor", cm_anchor, BRACE_ARGS },
122   { "appendix", cm_appendix, NO_BRACE_ARGS },
123   { "appendixsection", cm_appendixsec, NO_BRACE_ARGS },
124   { "appendixsec", cm_appendixsec, NO_BRACE_ARGS },
125   { "appendixsubsec", cm_appendixsubsec, NO_BRACE_ARGS },
126   { "appendixsubsubsec", cm_appendixsubsubsec, NO_BRACE_ARGS },
127   { "asis", cm_no_op, BRACE_ARGS },
128   { "b", cm_b, BRACE_ARGS },
129   { "bullet", cm_bullet, BRACE_ARGS },
130   { "bye", cm_bye, NO_BRACE_ARGS },
131   { "c", cm_ignore_line, NO_BRACE_ARGS },
132   { "cartouche", cm_cartouche, NO_BRACE_ARGS },
133   { "center", cm_center, NO_BRACE_ARGS },
134   { "centerchap", cm_unnumbered, NO_BRACE_ARGS },
135   { "chapheading", cm_chapheading, NO_BRACE_ARGS },
136   { "chapter", cm_chapter, NO_BRACE_ARGS },
137   { "cindex", cm_cindex, NO_BRACE_ARGS },
138   { "cite", cm_cite, BRACE_ARGS },
139   { "clear", cm_clear, NO_BRACE_ARGS },
140   { "code", cm_code, BRACE_ARGS },
141   { "command", cm_code, BRACE_ARGS },
142   { "comment", cm_ignore_line, NO_BRACE_ARGS },
143   { "contents", cm_contents, NO_BRACE_ARGS },
144   { "copying", cm_copying, NO_BRACE_ARGS },
145   { "copyright", cm_copyright, BRACE_ARGS },
146   { "ctrl", cm_obsolete, BRACE_ARGS },
147   { "defcodeindex", cm_defcodeindex, NO_BRACE_ARGS },
148   { "defcv", cm_defun, NO_BRACE_ARGS },
149   { "defcvx", cm_defun, NO_BRACE_ARGS },
150   { "deffn", cm_defun, NO_BRACE_ARGS },
151   { "deffnx", cm_defun, NO_BRACE_ARGS },
152   { "defindex", cm_defindex, NO_BRACE_ARGS },
153   { "definfoenclose", cm_definfoenclose, NO_BRACE_ARGS },
154   { "defivar", cm_defun, NO_BRACE_ARGS },
155   { "defivarx", cm_defun, NO_BRACE_ARGS },
156   { "defmac", cm_defun, NO_BRACE_ARGS },
157   { "defmacx", cm_defun, NO_BRACE_ARGS },
158   { "defmethod", cm_defun, NO_BRACE_ARGS },
159   { "defmethodx", cm_defun, NO_BRACE_ARGS },
160   { "defop", cm_defun, NO_BRACE_ARGS },
161   { "defopt", cm_defun, NO_BRACE_ARGS },
162   { "defoptx", cm_defun, NO_BRACE_ARGS },
163   { "defopx", cm_defun, NO_BRACE_ARGS },
164   { "defspec", cm_defun, NO_BRACE_ARGS },
165   { "defspecx", cm_defun, NO_BRACE_ARGS },
166   { "deftp", cm_defun, NO_BRACE_ARGS },
167   { "deftpx", cm_defun, NO_BRACE_ARGS },
168   { "deftypefn", cm_defun, NO_BRACE_ARGS },
169   { "deftypefnx", cm_defun, NO_BRACE_ARGS },
170   { "deftypefun", cm_defun, NO_BRACE_ARGS },
171   { "deftypefunx", cm_defun, NO_BRACE_ARGS },
172   { "deftypeivar", cm_defun, NO_BRACE_ARGS },
173   { "deftypeivarx", cm_defun, NO_BRACE_ARGS },
174   { "deftypemethod", cm_defun, NO_BRACE_ARGS },
175   { "deftypemethodx", cm_defun, NO_BRACE_ARGS },
176   { "deftypeop", cm_defun, NO_BRACE_ARGS },
177   { "deftypeopx", cm_defun, NO_BRACE_ARGS },
178   { "deftypevar", cm_defun, NO_BRACE_ARGS },
179   { "deftypevarx", cm_defun, NO_BRACE_ARGS },
180   { "deftypevr", cm_defun, NO_BRACE_ARGS },
181   { "deftypevrx", cm_defun, NO_BRACE_ARGS },
182   { "defun", cm_defun, NO_BRACE_ARGS },
183   { "defunx", cm_defun, NO_BRACE_ARGS },
184   { "defvar", cm_defun, NO_BRACE_ARGS },
185   { "defvarx", cm_defun, NO_BRACE_ARGS },
186   { "defvr", cm_defun, NO_BRACE_ARGS },
187   { "defvrx", cm_defun, NO_BRACE_ARGS },
188   { "detailmenu", cm_detailmenu, NO_BRACE_ARGS },
189   { "dfn", cm_dfn, BRACE_ARGS },
190   { "dircategory", cm_dircategory, NO_BRACE_ARGS },
191   { "direntry", cm_direntry, NO_BRACE_ARGS },
192   { "display", cm_display, NO_BRACE_ARGS },
193   { "dmn", cm_no_op, BRACE_ARGS },
194   { "documentdescription", cm_documentdescription, NO_BRACE_ARGS },
195   { "documentencoding", cm_documentencoding, NO_BRACE_ARGS },
196   { "documentlanguage", cm_documentlanguage, NO_BRACE_ARGS },
197   { "dotaccent", cm_accent, MAYBE_BRACE_ARGS },
198   { "dotless", cm_dotless, BRACE_ARGS },
199   { "dots", cm_dots, BRACE_ARGS },
200   { "email", cm_email, BRACE_ARGS },
201   { "emph", cm_emph, BRACE_ARGS },
202   { "end", cm_end, NO_BRACE_ARGS },
203   { "enddots", cm_enddots, BRACE_ARGS },
204   { "enumerate", cm_enumerate, NO_BRACE_ARGS },
205   { "env", cm_code, BRACE_ARGS },
206   { "equiv", cm_equiv, BRACE_ARGS },
207   { "error", cm_error, BRACE_ARGS },
208   { "evenfooting", cm_ignore_line, NO_BRACE_ARGS },
209   { "evenheading", cm_ignore_line, NO_BRACE_ARGS },
210   { "everyfooting", cm_ignore_line, NO_BRACE_ARGS },
211   { "everyheading", cm_ignore_line, NO_BRACE_ARGS },
212   { "example", cm_example, NO_BRACE_ARGS },
213   { "exampleindent", cm_exampleindent, NO_BRACE_ARGS },
214   { "exclamdown", cm_special_char, BRACE_ARGS },
215   { "exdent", cm_exdent, NO_BRACE_ARGS },
216   { "expansion", cm_expansion, BRACE_ARGS },
217   { "file", cm_code, BRACE_ARGS },
218   { "finalout", cm_no_op, NO_BRACE_ARGS },
219   { "findex", cm_findex, NO_BRACE_ARGS },
220   { "flushleft", cm_flushleft, NO_BRACE_ARGS },
221   { "flushright", cm_flushright, NO_BRACE_ARGS },
222   { "footnote", cm_footnote, NO_BRACE_ARGS}, /* self-arg eater */
223   { "footnotestyle", cm_footnotestyle, NO_BRACE_ARGS },
224   { "format", cm_format, NO_BRACE_ARGS },
225   { "ftable", cm_ftable, NO_BRACE_ARGS },
226   { "group", cm_group, NO_BRACE_ARGS },
227   { "heading", cm_heading, NO_BRACE_ARGS },
228   { "headings", cm_ignore_line, NO_BRACE_ARGS },
229   { "html", cm_html, NO_BRACE_ARGS },
230   { "hyphenation", cm_ignore_arg, BRACE_ARGS },
231   { "i", cm_i, BRACE_ARGS },
232   { "ifclear", cm_ifclear, NO_BRACE_ARGS },
233   { "ifeq", cm_ifeq, NO_BRACE_ARGS },
234   { "ifhtml", cm_ifhtml, NO_BRACE_ARGS },
235   { "ifinfo", cm_ifinfo, NO_BRACE_ARGS },
236   { "ifnothtml", cm_ifnothtml, NO_BRACE_ARGS },
237   { "ifnotinfo", cm_ifnotinfo, NO_BRACE_ARGS },
238   { "ifnotplaintext", cm_ifnotplaintext, NO_BRACE_ARGS },
239   { "ifnottex", cm_ifnottex, NO_BRACE_ARGS },
240   { "ifplaintext", cm_ifplaintext, NO_BRACE_ARGS },
241   { "ifset", cm_ifset, NO_BRACE_ARGS },
242   { "iftex", cm_iftex, NO_BRACE_ARGS },
243   { "ignore", command_name_condition, NO_BRACE_ARGS },
244   { "image", cm_image, BRACE_ARGS },
245   { "include", cm_include, NO_BRACE_ARGS },
246   { "inforef", cm_inforef, BRACE_ARGS },
247   { "insertcopying", cm_insert_copying, NO_BRACE_ARGS },
248   { "item", cm_item, NO_BRACE_ARGS },
249   { "itemize", cm_itemize, NO_BRACE_ARGS },
250   { "itemx", cm_itemx, NO_BRACE_ARGS },
251   { "kbd", cm_kbd, BRACE_ARGS },
252   { "kbdinputstyle", cm_ignore_line, NO_BRACE_ARGS },
253   { "key", cm_key, BRACE_ARGS },
254   { "kindex", cm_kindex, NO_BRACE_ARGS },
255   { "l", cm_special_char, BRACE_ARGS },
256   { "lisp", cm_lisp, NO_BRACE_ARGS },
257   { "lowersections", cm_lowersections, NO_BRACE_ARGS },
258   { "macro", cm_macro, NO_BRACE_ARGS },
259   { "majorheading", cm_majorheading, NO_BRACE_ARGS },
260   { "math", cm_no_op, BRACE_ARGS },
261   { "menu", cm_menu, NO_BRACE_ARGS },
262   { "minus", cm_minus, BRACE_ARGS },
263   { "multitable", cm_multitable, NO_BRACE_ARGS },
264   { "need", cm_ignore_line, NO_BRACE_ARGS },
265   { "node", cm_node, NO_BRACE_ARGS },
266   { "noindent", cm_noindent, NO_BRACE_ARGS },
267   { "noindent", cm_novalidate, NO_BRACE_ARGS },
268   { "nwnode", cm_node, NO_BRACE_ARGS },
269   { "o", cm_special_char, BRACE_ARGS },
270   { "oddfooting", cm_ignore_line, NO_BRACE_ARGS },
271   { "oddheading", cm_ignore_line, NO_BRACE_ARGS },
272   { "oe", cm_special_char, BRACE_ARGS },
273   { "option", cm_code, BRACE_ARGS },
274   { "page", cm_no_op, NO_BRACE_ARGS },
275   { "pagesizes", cm_ignore_line, NO_BRACE_ARGS },
276   { "paragraphindent", cm_paragraphindent, NO_BRACE_ARGS },
277   { "pindex", cm_pindex, NO_BRACE_ARGS },
278   { "point", cm_point, BRACE_ARGS },
279   { "pounds", cm_special_char, BRACE_ARGS },
280   { "print", cm_print, BRACE_ARGS },
281   { "printindex", cm_printindex, NO_BRACE_ARGS },
282   { "pxref", cm_pxref, BRACE_ARGS },
283   { "questiondown", cm_special_char, BRACE_ARGS },
284   { "quotation", cm_quotation, NO_BRACE_ARGS },
285   { "r", cm_r, BRACE_ARGS },
286   { "raisesections", cm_raisesections, NO_BRACE_ARGS },
287   { "ref", cm_ref, BRACE_ARGS },
288   { "refill", cm_no_op, NO_BRACE_ARGS },
289   { "result", cm_result, BRACE_ARGS },
290   { "ringaccent", cm_accent, MAYBE_BRACE_ARGS },
291   { "rmacro", cm_rmacro, NO_BRACE_ARGS },
292   { "samp", cm_code, BRACE_ARGS },
293   { "sc", cm_sc, BRACE_ARGS },
294   { "section", cm_section, NO_BRACE_ARGS },
295   { "set", cm_set, NO_BRACE_ARGS },
296   { "setchapternewpage", cm_ignore_line, NO_BRACE_ARGS },
297   { "setchapterstyle", cm_obsolete, NO_BRACE_ARGS },
298   { "setcontentsaftertitlepage", cm_no_op, NO_BRACE_ARGS },
299   { "setfilename", cm_setfilename, NO_BRACE_ARGS },
300   { "setshortcontentsaftertitlepage", cm_no_op, NO_BRACE_ARGS },
301   { "settitle", cm_settitle, NO_BRACE_ARGS },
302   { "shortcontents", cm_shortcontents, NO_BRACE_ARGS },
303   { "shorttitlepage", cm_ignore_line, NO_BRACE_ARGS },
304   { "smallbook", cm_ignore_line, NO_BRACE_ARGS },
305   { "smalldisplay", cm_smalldisplay, NO_BRACE_ARGS },
306   { "smallexample", cm_smallexample, NO_BRACE_ARGS },
307   { "smallformat", cm_smallformat, NO_BRACE_ARGS },
308   { "smalllisp", cm_smalllisp, NO_BRACE_ARGS },
309   { "sp", cm_sp, NO_BRACE_ARGS },
310   { "ss", cm_special_char, BRACE_ARGS },
311   { "strong", cm_strong, BRACE_ARGS },
312   { "subheading", cm_subheading, NO_BRACE_ARGS },
313   { "subsection", cm_subsection, NO_BRACE_ARGS },
314   { "subsubheading", cm_subsubheading, NO_BRACE_ARGS },
315   { "subsubsection", cm_subsubsection, NO_BRACE_ARGS },
316   { "summarycontents", cm_shortcontents, NO_BRACE_ARGS },
317   { "syncodeindex", cm_synindex, NO_BRACE_ARGS },
318   { "synindex", cm_synindex, NO_BRACE_ARGS },
319   { "t", cm_tt, BRACE_ARGS },
320   { "tab", cm_tab, NO_BRACE_ARGS },
321   { "table", cm_table, NO_BRACE_ARGS },
322   { "tex", cm_tex, NO_BRACE_ARGS },
323   { "tieaccent", cm_accent, MAYBE_BRACE_ARGS },
324   { "tindex", cm_tindex, NO_BRACE_ARGS },
325   { "titlefont", cm_titlefont, BRACE_ARGS },
326   { "titlepage", command_name_condition, 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_url, 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   { "w", cm_w, 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 \f
372 /* The bulk of the Texinfo commands. */
373
374 /* Commands which insert their own names. */
375 void
376 insert_self (arg)
377     int arg;
378 {
379   if (arg == START)
380     add_word (command);
381 }
382
383 void
384 insert_space (arg)
385     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 /* Force a line break in the output. */
397 void
398 cm_asterisk ()
399 {
400   if (html)
401     add_word ("<br>");
402   else if (xml && !docbook)
403     xml_insert_entity ("linebreak");
404   else if (docbook) 
405     xml_asterisk ();
406   else
407     {
408       close_single_paragraph ();
409       cm_noindent ();
410     }
411 }
412
413 /* Insert ellipsis. */
414 void
415 cm_dots (arg)
416      int arg;
417 {
418   if (arg == START)
419     {
420       if (xml && !docbook)
421         xml_insert_entity ("dots");
422       else if (docbook)
423         xml_insert_entity ("hellip");
424       else
425         add_word (html ? "<small>...</small>" : "...");
426     }
427 }
428
429 /* Insert ellipsis for sentence end. */
430 void
431 cm_enddots (arg)
432      int arg;
433 {
434   if (arg == START)
435     {
436       if (xml && !docbook)
437         xml_insert_entity ("enddots");
438       else if (docbook)
439         {
440           xml_insert_entity ("hellip");
441           add_char ('.');
442         }
443       else
444         add_word (html ? "<small>...</small>." : "....");
445     }
446 }
447
448 void
449 cm_bullet (arg)
450      int arg;
451 {
452   if (arg == START)
453     {
454       if (html)
455         add_word ("&#149;");
456       else if (xml && !docbook)
457         xml_insert_entity ("bullet");
458       else if (docbook)
459         xml_insert_entity ("bull");
460       else
461         add_char ('*');
462     }
463 }
464
465 void
466 cm_minus (arg)
467      int arg;
468 {
469   if (arg == START)
470     {
471       if (xml)
472         xml_insert_entity ("minus");
473       else
474         add_char ('-');
475     }
476 }
477
478 /* Insert "TeX". */
479 void
480 cm_TeX (arg)
481      int arg;
482 {
483   if (arg == START)
484     {
485       if (xml && ! docbook)
486         xml_insert_entity ("tex");
487       else
488         add_word ("TeX");
489     }
490 }
491
492 /* Copyright symbol.  */
493 void
494 cm_copyright (arg)
495     int arg;
496 {
497   if (arg == START)
498     {
499     if (html)
500       add_word ("&copy;");
501     else if (xml && !docbook)
502       xml_insert_entity ("copyright");
503     else if (docbook)
504       xml_insert_entity ("copy");
505     else
506       add_word ("(C)");
507     }
508 }
509
510 void
511 cm_today (arg)
512      int arg;
513 {
514   static char *months[12] =
515     { N_("January"), N_("February"), N_("March"), N_("April"), N_("May"),
516       N_("June"), N_("July"), N_("August"), N_("September"), N_("October"),
517       N_("November"), N_("December") };
518   if (arg == START)
519     {
520       time_t timer = time (0);
521       struct tm *ts = localtime (&timer);
522       add_word_args ("%d %s %d", ts->tm_mday, _(months[ts->tm_mon]),
523                      ts->tm_year + 1900);
524     }
525 }
526
527 void
528 cm_acronym (arg)
529      int arg;
530 {
531   if (html)
532     insert_html_tag (arg, small_tag);
533   else if (xml)
534     xml_insert_element (ACRONYM, arg);
535 }
536
537 void
538 cm_tt (arg)
539      int arg;
540 {
541   /* @t{} is a no-op in Info.  */
542   if (html)
543     insert_html_tag (arg, "tt");
544   else if (xml)
545     xml_insert_element (TT, arg);
546 }
547
548 void
549 cm_code (arg)
550      int arg;
551 {
552   if (xml)
553     xml_insert_element (CODE, arg);
554   else
555     {
556   extern int printing_index;
557
558   if (arg == START)
559     {
560       in_fixed_width_font++;
561
562       if (html)
563         insert_html_tag (arg, "code");
564       else if (!printing_index)
565         add_char ('`');
566     }
567   else if (html)
568     insert_html_tag (arg, "code");
569   else
570     {
571       if (!printing_index)
572         add_meta_char ('\'');
573     }
574     }
575 }
576
577 void
578 cm_kbd (arg)
579      int arg;
580 {
581   if (xml)
582     xml_insert_element (KBD, arg);
583   else if (html)
584     { /* Seems like we should increment in_fixed_width_font for Info
585          format too, but then the quote-omitting special case gets
586          confused.  Punt.  */
587       if (arg == START)
588         in_fixed_width_font++;
589       insert_html_tag (arg, "kbd");
590     }
591   else
592     { /* People use @kbd in an example to get the "user input" font.
593          We don't want quotes in that case.  */
594       if (!in_fixed_width_font)
595         cm_code (arg);
596     }
597 }
598
599 void
600 cm_url (arg, start, end)
601 {
602   if (xml)
603     xml_insert_element (URL, arg);
604   else if (html)
605     {
606       if (arg == START)
607         add_word ("&lt;<code>");
608       else
609         add_word ("</code>&gt;");
610     }
611   else
612     if (arg == START)
613       add_word ("<");
614     else
615       add_word (">");
616 }
617
618 void
619 cm_key (arg)
620      int arg;
621 {
622   if (xml)
623     xml_insert_element (KEY, arg);
624   else if (html)
625     add_word (arg == START ? "&lt;" : "&gt;");
626   else
627     add_char (arg == START ? '<' : '>');
628 }
629
630 /* Handle a command that switches to a non-fixed-width font.  */
631 void
632 not_fixed_width (arg)
633      int arg;
634 {
635   if (arg == START)
636     in_fixed_width_font = 0;
637 }
638
639 /* @var in makeinfo just uppercases the text. */
640 void
641 cm_var (arg, start_pos, end_pos)
642      int arg, start_pos, end_pos;
643 {
644   if (xml)
645     xml_insert_element (VAR, arg);
646   else
647     {
648   not_fixed_width (arg);
649
650   if (html)
651     insert_html_tag (arg, "var");
652   else if (arg == END)
653     {
654       while (start_pos < end_pos)
655         {
656           unsigned char c = output_paragraph[start_pos];
657           if (strchr ("[](),", c))
658             warning (_("unlikely character %c in @var"), c);
659           output_paragraph[start_pos] = coerce_to_upper (c);
660           start_pos++;
661         }
662     }
663     }
664 }
665
666 void
667 cm_sc (arg, start_pos, end_pos)
668      int arg, start_pos, end_pos;
669 {
670   if (xml)
671     xml_insert_element (SC, arg);
672   else
673     {
674   not_fixed_width (arg);
675
676   if (arg == START)
677     {
678       if (html)
679         insert_html_tag (arg, small_tag);
680     }
681   else
682     {
683       int all_upper;
684
685       if (html)
686         start_pos += sizeof (small_tag) + 2 - 1; /* skip <small> */
687
688       /* Avoid the warning below if there's no text inside @sc{}, or
689          when processing menus under --no-headers.  */
690       all_upper = start_pos < end_pos;
691
692       while (start_pos < end_pos)
693         {
694           unsigned char c = output_paragraph[start_pos];
695           if (!isupper (c))
696             all_upper = 0;
697           output_paragraph[start_pos] = coerce_to_upper (c);
698           start_pos++;
699         }
700       if (all_upper)
701         warning (_("@sc argument all uppercase, thus no effect"));
702         
703       if (html)
704         insert_html_tag (arg, small_tag);
705     }
706     }
707 }
708
709 void
710 cm_dfn (arg, position)
711      int arg, position;
712 {
713   if (xml)
714     xml_insert_element (DFN, arg);
715   else
716     {
717   if (html)
718     insert_html_tag (arg, "dfn");
719   else if (arg == START)
720     add_char ('"');
721   else
722     add_meta_char ('"');
723     }
724 }
725
726 void
727 cm_emph (arg)
728      int arg;
729 {
730   if (xml)
731     xml_insert_element (EMPH, arg);
732   else if (html)
733     insert_html_tag (arg, "em");
734   else
735     add_char ('_');
736 }
737
738 void
739 cm_verb (arg)
740      int arg;
741 {
742   int character;
743   int delimiter;
744   int seen_end = 0;
745
746   in_fixed_width_font++;
747   /* are these necessary ? */
748   last_char_was_newline = 0;
749
750   if (html)
751     add_word ("<pre>");
752
753   if (input_text_offset < input_text_length)
754     {
755       character = curchar ();
756       if (character == '{')
757         input_text_offset++;
758       else
759         line_error (_("`{' expected, but saw `%c'"), character);
760     }
761     
762   if (input_text_offset < input_text_length)
763     {
764       delimiter = curchar ();
765       input_text_offset++;
766     }
767
768   while (input_text_offset < input_text_length)
769     {
770       character = curchar ();
771
772       if (character == '\n')
773         line_number++;
774       /*
775         Assume no newlines in END_VERBATIM
776       */
777       else if (character == delimiter)
778         {
779           seen_end = 1;
780           input_text_offset++;
781           break;
782         }
783
784       add_char (character);
785       input_text_offset++;
786     }
787
788   if (!seen_end)
789     warning (_("end of file inside verb block"));
790   
791   if (input_text_offset < input_text_length)
792     {
793       character = curchar ();
794       if (character == '}')
795         input_text_offset++;
796       else
797         line_error (_("`}' expected, but saw `%c'"), character);
798     }
799
800   if (html)
801     add_word ("</pre>");
802 }
803
804 void
805 cm_strong (arg, position)
806      int arg, position;
807 {
808   if (xml)
809     xml_insert_element (STRONG, arg);
810   else if (html)
811     insert_html_tag (arg, "strong");
812   else
813     add_char ('*');
814 }
815
816 void
817 cm_cite (arg, position)
818      int arg, position;
819 {
820   if (xml)
821     xml_insert_element (CITE, arg);        
822   else if (html)
823     insert_html_tag (arg, "cite");
824   else
825     {
826       if (arg == START)
827         add_char ('`');
828       else
829         add_char ('\'');
830     }
831 }
832
833 /* No highlighting, but argument switches fonts.  */
834 void
835 cm_not_fixed_width (arg, start, end)
836      int arg, start, end;
837 {
838   if (xml)
839     xml_insert_element (NOTFIXEDWIDTH, arg);
840   not_fixed_width (arg);
841 }
842
843 void
844 cm_i (arg)
845      int arg;
846 {
847   if (xml)
848     xml_insert_element (I, arg);
849   else if (html)
850     insert_html_tag (arg, "i");
851   else
852     not_fixed_width (arg);
853 }
854
855 void
856 cm_b (arg)
857      int arg;
858 {
859   if (xml)
860     xml_insert_element (B, arg);
861   else if (html)
862     insert_html_tag (arg, "b");
863   else
864     not_fixed_width (arg);
865 }
866
867 void
868 cm_r (arg)
869      int arg;
870 {
871   if (xml)
872     xml_insert_element (R, arg);
873   else
874     {
875       extern int printing_index;
876
877       /* People use @r{} in index entries like this:
878          
879       @findex foo@r{, some text}
880       
881       This is supposed to produce output as if the entry were saying
882       "@code{foo}, some text", since the "fn" index is typeset as
883       @code.  The following attempts to do the same in HTML.  Note that
884       this relies on the fact that only @code bumps up the variable
885       in_fixed_width_font while processing index entries in HTML mode.  */
886       if (html && printing_index)
887         {
888           int level = in_fixed_width_font;
889           
890           while (level--)
891             insert_html_tag (arg == START ? END : START, "code");
892         }
893       
894       not_fixed_width (arg);
895     }
896 }
897
898 void
899 cm_titlefont (arg)
900      int arg;
901 {
902   if (xml)
903     xml_insert_element (TITLEFONT, arg);
904   else
905   not_fixed_width (arg);
906 }
907
908 /* Various commands are no-op's. */
909 void
910 cm_no_op ()
911 {
912 }
913
914
915 /* For proofing single chapters, etc.  */
916 void
917 cm_novalidate ()
918 {
919   validating = 0;
920 }
921
922
923 /* Prevent the argument from being split across two lines. */
924 void
925 cm_w (arg, start, end)
926      int arg, start, end;
927 {
928   if (arg == START)
929     non_splitting_words++;
930   else
931     non_splitting_words--;
932 }
933
934
935 /* Explain that this command is obsolete, thus the user shouldn't
936    do anything with it. */
937 static void
938 cm_obsolete (arg, start, end)
939      int arg, start, end;
940 {
941   if (arg == START)
942     warning (_("%c%s is obsolete"), COMMAND_PREFIX, command);
943 }
944
945
946 /* This says to inhibit the indentation of the next paragraph, but
947    not of following paragraphs.  */
948 void
949 cm_noindent ()
950 {
951   if (!inhibit_paragraph_indentation)
952     inhibit_paragraph_indentation = -1;
953 }
954
955 /* I don't know exactly what to do with this.  Should I allow
956    someone to switch filenames in the middle of output?  Since the
957    file could be partially written, this doesn't seem to make sense.
958    Another option: ignore it, since they don't *really* want to
959    switch files.  Finally, complain, or at least warn.  It doesn't
960    really matter, anyway, since this doesn't get executed.  */
961 void
962 cm_setfilename ()
963 {
964   char *filename;
965   get_rest_of_line (1, &filename);
966   /* warning ("`@%s %s' encountered and ignored", command, filename); */
967   if (xml)
968     add_word_args ("<setfilename>%s</setfilename>", filename);
969   free (filename);
970 }
971
972 void
973 cm_settitle ()
974 {
975   if (xml)
976     {
977       xml_begin_document (current_output_filename);
978       xml_insert_element (SETTITLE, START);
979       get_rest_of_line (0, &title);
980       execute_string ("%s", title);
981       xml_insert_element (SETTITLE, END);
982     }
983   else
984     get_rest_of_line (0, &title);
985 }
986
987
988 /* Ignore argument in braces.  */
989 void
990 cm_ignore_arg (arg, start_pos, end_pos)
991      int arg, start_pos, end_pos;
992 {
993   if (arg == END)
994     output_paragraph_offset = start_pos;
995 }
996
997 /* Ignore argument on rest of line.  */
998 void
999 cm_ignore_line ()
1000 {
1001   discard_until ("\n");
1002 }
1003
1004 /* Insert the number of blank lines passed as argument. */
1005 void
1006 cm_sp ()
1007 {
1008   int lines;
1009   char *line;
1010
1011   get_rest_of_line (1, &line);
1012
1013   if (sscanf (line, "%d", &lines) != 1 || lines <= 0)
1014     line_error (_("@sp requires a positive numeric argument, not `%s'"), line);
1015   else
1016     {
1017       if (xml)
1018         {
1019           xml_insert_element_with_attribute (SP, START, "lines=\"%s\"", line);
1020           /*      insert_string (line);*/
1021           xml_insert_element (SP, END);
1022         }
1023       else
1024         {
1025           /* Must disable filling since otherwise multiple newlines is like
1026          multiple spaces.  Must close paragraph since that's what the
1027          manual says and that's what TeX does.  */
1028       int save_filling_enabled = filling_enabled;
1029       filling_enabled = 0;
1030       
1031       /* close_paragraph generates an extra blank line.  */
1032       close_single_paragraph ();
1033
1034       if (lines && html && !executing_string)
1035         html_output_head ();
1036
1037       while (lines--)
1038         {
1039           if (html)
1040             insert_string ("<br><p>\n");
1041           else
1042             add_char ('\n');
1043         }
1044
1045       filling_enabled = save_filling_enabled;
1046     }
1047     }
1048   free (line);
1049 }
1050
1051 /* @dircategory LINE outputs INFO-DIR-SECTION LINE, unless --no-headers.  */ 
1052 void
1053 cm_dircategory ()
1054 {
1055   char *line;
1056
1057   if (html || docbook)
1058     cm_ignore_line ();
1059   else if (xml)
1060     {
1061       xml_insert_element (DIRCATEGORY, START);
1062       get_rest_of_line (1, &line);
1063       insert_string (line);
1064       free (line);
1065       xml_insert_element (DIRCATEGORY, END);
1066     }
1067   else
1068     {
1069       get_rest_of_line (1, &line);
1070
1071       if (!no_headers && !html)
1072         {
1073           kill_self_indent (-1); /* make sure there's no indentation */
1074           insert_string ("INFO-DIR-SECTION ");
1075           insert_string (line);
1076           insert ('\n');
1077         }
1078
1079       free (line);
1080     }
1081 }
1082
1083 /* Start a new line with just this text on it.
1084    Then center the line of text.
1085    */
1086 void
1087 cm_center ()
1088 {
1089   if (xml)
1090     {
1091       unsigned char *line;
1092       xml_insert_element (CENTER, START);
1093       get_rest_of_line (0, (char **)&line);
1094       execute_string ("%s", (char *)line);
1095       free (line);
1096       xml_insert_element (CENTER, END);
1097     }
1098   else
1099     {
1100   int i, start, length;
1101   unsigned char *line;
1102   int save_indented_fill = indented_fill;
1103   int save_filling_enabled = filling_enabled;
1104   int fudge_factor = 1;
1105
1106   filling_enabled = indented_fill = 0;
1107   cm_noindent ();
1108   start = output_paragraph_offset;
1109
1110   if (html)
1111     add_word ("<div align=\"center\">");
1112
1113   inhibit_output_flushing ();
1114   get_rest_of_line (0, (char **)&line);
1115   execute_string ("%s", (char *)line);
1116   free (line);
1117   uninhibit_output_flushing ();
1118    if (html)
1119     add_word ("</div>");
1120
1121    else
1122      {
1123        i = output_paragraph_offset - 1;
1124        while (i > (start - 1) && output_paragraph[i] == '\n')
1125          i--;
1126
1127        output_paragraph_offset = ++i;
1128        length = output_paragraph_offset - start;
1129
1130        if (length < (fill_column - fudge_factor))
1131          {
1132            line = xmalloc (1 + length);
1133            memcpy (line, (char *)(output_paragraph + start), length);
1134
1135            i = (fill_column - fudge_factor - length) / 2;
1136            output_paragraph_offset = start;
1137
1138            while (i--)
1139              insert (' ');
1140
1141            for (i = 0; i < length; i++)
1142              insert (line[i]);
1143
1144            free (line);
1145          }
1146      }
1147
1148   insert ('\n');
1149   filling_enabled = save_filling_enabled;
1150   indented_fill = save_indented_fill;
1151     }
1152 }
1153
1154 /* Show what an expression returns. */
1155 void
1156 cm_result (arg)
1157      int arg;
1158 {
1159   if (arg == END)
1160     add_word (html ? "=&gt;" : "=>");
1161 }
1162
1163 /* What an expression expands to. */
1164 void
1165 cm_expansion (arg)
1166      int arg;
1167 {
1168   if (arg == END)
1169     add_word (html ? "==&gt;" : "==>");
1170 }
1171
1172 /* Indicates two expressions are equivalent. */
1173 void
1174 cm_equiv (arg)
1175      int arg;
1176 {
1177   if (arg == END)
1178     add_word ("==");
1179 }
1180
1181 /* What an expression may print. */
1182 void
1183 cm_print (arg)
1184      int arg;
1185 {
1186   if (arg == END)
1187     add_word ("-|");
1188 }
1189
1190 /* An error signaled. */
1191 void
1192 cm_error (arg)
1193      int arg;
1194 {
1195   if (arg == END)
1196     add_word (html ? "error--&gt;" : "error-->");
1197 }
1198
1199 /* The location of point in an example of a buffer. */
1200 void
1201 cm_point (arg)
1202      int arg;
1203 {
1204   if (arg == END)
1205     add_word ("-!-");
1206 }
1207
1208 /* @exdent: Start a new line with just this text on it.
1209    The text is outdented one level if possible. */
1210 void
1211 cm_exdent ()
1212 {
1213   char *line;
1214   int save_indent = current_indent;
1215   int save_in_fixed_width_font = in_fixed_width_font;
1216
1217   /* Read argument  */
1218   get_rest_of_line (0, &line);
1219
1220   /* Exdent the output.  Actually this may be a no-op.   */
1221   if (current_indent)
1222     current_indent -= default_indentation_increment;
1223
1224   /* @exdent arg is supposed to be in roman.  */
1225   in_fixed_width_font = 0;
1226   
1227   /* The preceding newline already inserted the `current_indent'.
1228      Remove one level's worth.  */
1229   kill_self_indent (default_indentation_increment);
1230
1231   if (html)
1232     add_word ("<br>");
1233
1234   /* Can't close_single_paragraph, then we lose preceding blank lines.  */
1235   flush_output ();
1236   execute_string ("%s", line);
1237   free (line);
1238
1239   if (html)
1240     add_word ("<br>");
1241   close_single_paragraph ();
1242
1243   current_indent = save_indent;
1244   in_fixed_width_font = save_in_fixed_width_font;
1245 }
1246
1247 /* 
1248   Read include-filename, process the include-file:
1249     verbatim_include == 0: process through reader_loop
1250     verbatim_include != 0: process through handle_verbatim_environment
1251  */
1252 static void
1253 handle_include (verbatim_include)
1254   int verbatim_include;
1255 {
1256   char *filename;
1257
1258   if (macro_expansion_output_stream && !executing_string)
1259     me_append_before_this_command ();
1260
1261   close_paragraph ();
1262   get_rest_of_line (0, &filename);
1263
1264   if (macro_expansion_output_stream && !executing_string)
1265     remember_itext (input_text, input_text_offset);
1266
1267   pushfile ();
1268
1269   /* In verbose mode we print info about including another file. */
1270   if (verbose_mode)
1271     {
1272       int i = 0;
1273       FSTACK *stack = filestack;
1274
1275       for (i = 0, stack = filestack; stack; stack = stack->next, i++);
1276
1277       i *= 2;
1278
1279       printf ("%*s", i, "");
1280       printf ("%c%s `%s'\n", COMMAND_PREFIX, command, filename);
1281       fflush (stdout);
1282     }
1283
1284   if (!find_and_load (filename))
1285     {
1286       popfile ();
1287       line_number--;
1288
1289       /* /wh/bar:5: @include/@verbatiminclude `foo': No such file or dir */
1290       line_error ("%c%s `%s': %s", COMMAND_PREFIX, command, filename,
1291                   strerror (errno));
1292
1293       free (filename);
1294       return;
1295     }
1296   else
1297     {
1298       if (macro_expansion_output_stream && !executing_string)
1299         remember_itext (input_text, input_text_offset);
1300
1301       if (!verbatim_include)
1302         reader_loop ();
1303       else
1304         handle_verbatim_environment (0);
1305     }
1306   free (filename);
1307   popfile ();
1308 }
1309
1310
1311 /* Include file as if put in @verbatim environment */
1312 void
1313 cm_verbatiminclude ()
1314 {
1315   handle_include (1); 
1316 }
1317
1318
1319 /* Remember this file, and move onto the next. */
1320 void
1321 cm_include ()
1322 {
1323   handle_include (0); 
1324 }
1325
1326
1327 /* @bye: Signals end of processing.  Easy to make this happen. */
1328
1329 void
1330 cm_bye ()
1331 {
1332   discard_braces (); /* should not have any unclosed braces left */
1333   flush_output ();
1334   input_text_offset = input_text_length;
1335 }
1336 \f
1337 /* @paragraphindent */
1338
1339 static void
1340 cm_paragraphindent ()
1341 {
1342   char *arg;
1343
1344   get_rest_of_line (1, &arg);
1345   if (set_paragraph_indent (arg) != 0)
1346     line_error (_("Bad argument to %c%s"), COMMAND_PREFIX, command);
1347
1348   free (arg);
1349 }
1350
1351 /* @exampleindent: change indentation of example-like environments.   */
1352 static int
1353 set_default_indentation_increment (string)
1354      char *string;
1355 {
1356   if (strcmp (string, "asis") == 0 || strcmp (string, _("asis")) == 0)
1357     ;
1358   else if (strcmp (string, "none") == 0 || strcmp (string, _("none")) == 0)
1359     default_indentation_increment = 0;
1360   else if (sscanf (string, "%d", &default_indentation_increment) != 1)
1361     return -1;
1362   return 0;
1363 }
1364
1365 static void
1366 cm_exampleindent ()
1367 {
1368   char *arg;
1369   
1370   get_rest_of_line (1, &arg);
1371   if (set_default_indentation_increment (arg) != 0)
1372     line_error (_("Bad argument to %c%s"), COMMAND_PREFIX, command);
1373
1374   free (arg);
1375 }