Back to index

tetex-bin  3.0
cmds.c
Go to the documentation of this file.
00001 /* cmds.c -- Texinfo commands.
00002    $Id: cmds.c,v 1.55 2004/12/14 00:15:36 karl Exp $
00003 
00004    Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003, 2004 Free Software
00005    Foundation, Inc.
00006 
00007    This program is free software; you can redistribute it and/or modify
00008    it under the terms of the GNU General Public License as published by
00009    the Free Software Foundation; either version 2, or (at your option)
00010    any later version.
00011 
00012    This program is distributed in the hope that it will be useful,
00013    but WITHOUT ANY WARRANTY; without even the implied warranty of
00014    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00015    GNU General Public License for more details.
00016 
00017    You should have received a copy of the GNU General Public License
00018    along with this program; if not, write to the Free Software Foundation,
00019    Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */
00020 
00021 #include "system.h"
00022 #include "cmds.h"
00023 #include "defun.h"
00024 #include "files.h"
00025 #include "footnote.h"
00026 #include "html.h"
00027 #include "insertion.h"
00028 #include "lang.h"
00029 #include "macro.h"
00030 #include "makeinfo.h"
00031 #include "node.h"
00032 #include "sectioning.h"
00033 #include "toc.h"
00034 #include "xml.h"
00035 
00036 #ifdef TM_IN_SYS_TIME
00037 #include <sys/time.h>
00038 #else
00039 #include <time.h>
00040 #endif
00041 
00042 /* Options. */
00043 static void cm_exampleindent (void),
00044      cm_firstparagraphindent (void),
00045      cm_paragraphindent (void),
00046      cm_novalidate (void);
00047 
00048 /* Internals. */
00049 static void cm_obsolete (int arg, int start, int end),
00050      not_fixed_width (int arg);
00051 
00052 /* The dispatch table.  */
00053 COMMAND command_table[] = {
00054   { "\t", insert_space, NO_BRACE_ARGS },
00055   { "\n", insert_space, NO_BRACE_ARGS },
00056   { " ", insert_space, NO_BRACE_ARGS },
00057   { "!", cm_punct, NO_BRACE_ARGS },
00058   { "\"", cm_accent_umlaut, MAYBE_BRACE_ARGS },
00059   { "'", cm_accent_acute, MAYBE_BRACE_ARGS },
00060   { "*", cm_asterisk, NO_BRACE_ARGS },
00061   { ",", cm_accent_cedilla, MAYBE_BRACE_ARGS },
00062   { "-", cm_no_op, NO_BRACE_ARGS },
00063   { ".", cm_punct, NO_BRACE_ARGS },
00064   { "/", cm_no_op, NO_BRACE_ARGS },
00065   { ":", cm_colon, NO_BRACE_ARGS },
00066   { "=", cm_accent, MAYBE_BRACE_ARGS },
00067   { "?", cm_punct, NO_BRACE_ARGS },
00068   { "@", insert_self, NO_BRACE_ARGS },
00069   { "\\", insert_self, NO_BRACE_ARGS },
00070   { "^", cm_accent_hat, MAYBE_BRACE_ARGS },
00071   { "`", cm_accent_grave, MAYBE_BRACE_ARGS },
00072   { "{", insert_self, NO_BRACE_ARGS },
00073   { "|", cm_no_op, NO_BRACE_ARGS },
00074   { "}", insert_self, NO_BRACE_ARGS },
00075   { "~", cm_accent_tilde, MAYBE_BRACE_ARGS },
00076   { "AA", cm_special_char, BRACE_ARGS },
00077   { "AE", cm_special_char, BRACE_ARGS },
00078   { "H", cm_accent, MAYBE_BRACE_ARGS },
00079   { "L", cm_special_char, BRACE_ARGS },
00080   { "LaTeX", cm_LaTeX, BRACE_ARGS },
00081   { "O", cm_special_char, BRACE_ARGS },
00082   { "OE", cm_special_char, BRACE_ARGS },
00083   { "TeX", cm_TeX, BRACE_ARGS },
00084   { "aa", cm_special_char, BRACE_ARGS },
00085   { "abbr", cm_abbr, BRACE_ARGS },
00086   { "acronym", cm_acronym, BRACE_ARGS },
00087   { "ae", cm_special_char, BRACE_ARGS },
00088   { "afivepaper", cm_ignore_line, NO_BRACE_ARGS },
00089   { "afourlatex", cm_ignore_line, NO_BRACE_ARGS },
00090   { "afourpaper", cm_ignore_line, NO_BRACE_ARGS },
00091   { "afourwide", cm_ignore_line, NO_BRACE_ARGS },
00092   { "alias", cm_alias, NO_BRACE_ARGS },
00093   { "anchor", cm_anchor, BRACE_ARGS },
00094   { "appendix", cm_appendix, NO_BRACE_ARGS },
00095   { "appendixsection", cm_appendixsec, NO_BRACE_ARGS },
00096   { "appendixsec", cm_appendixsec, NO_BRACE_ARGS },
00097   { "appendixsubsec", cm_appendixsubsec, NO_BRACE_ARGS },
00098   { "appendixsubsubsec", cm_appendixsubsubsec, NO_BRACE_ARGS },
00099   { "asis", cm_no_op, BRACE_ARGS },
00100   { "author", cm_author, NO_BRACE_ARGS },
00101   { "b", cm_b, BRACE_ARGS },
00102   { "bullet", cm_bullet, BRACE_ARGS },
00103   { "bye", cm_bye, NO_BRACE_ARGS },
00104   { "c", cm_comment, NO_BRACE_ARGS },
00105   { "caption", cm_caption, BRACE_ARGS },
00106   { "cartouche", cm_cartouche, NO_BRACE_ARGS },
00107   { "center", cm_center, NO_BRACE_ARGS },
00108   { "centerchap", cm_unnumbered, NO_BRACE_ARGS },
00109   { "chapheading", cm_chapheading, NO_BRACE_ARGS },
00110   { "chapter", cm_chapter, NO_BRACE_ARGS },
00111   { "cindex", cm_cindex, NO_BRACE_ARGS },
00112   { "cite", cm_cite, BRACE_ARGS },
00113   { "clear", cm_clear, NO_BRACE_ARGS },
00114   { "code", cm_code, BRACE_ARGS },
00115   { "comma", cm_comma, BRACE_ARGS },
00116   { "command", cm_code, BRACE_ARGS },
00117   { "comment", cm_comment, NO_BRACE_ARGS },
00118   { "contents", cm_contents, NO_BRACE_ARGS },
00119   { "copying", cm_copying, NO_BRACE_ARGS },
00120   { "copyright", cm_copyright, BRACE_ARGS },
00121   { "ctrl", cm_obsolete, BRACE_ARGS },
00122   { "defcodeindex", cm_defcodeindex, NO_BRACE_ARGS },
00123   { "defcv", cm_defun, NO_BRACE_ARGS },
00124   { "defcvx", cm_defun, NO_BRACE_ARGS },
00125   { "deffn", cm_defun, NO_BRACE_ARGS },
00126   { "deffnx", cm_defun, NO_BRACE_ARGS },
00127   { "defindex", cm_defindex, NO_BRACE_ARGS },
00128   { "definfoenclose", cm_definfoenclose, NO_BRACE_ARGS },
00129   { "defivar", cm_defun, NO_BRACE_ARGS },
00130   { "defivarx", cm_defun, NO_BRACE_ARGS },
00131   { "defmac", cm_defun, NO_BRACE_ARGS },
00132   { "defmacx", cm_defun, NO_BRACE_ARGS },
00133   { "defmethod", cm_defun, NO_BRACE_ARGS },
00134   { "defmethodx", cm_defun, NO_BRACE_ARGS },
00135   { "defop", cm_defun, NO_BRACE_ARGS },
00136   { "defopt", cm_defun, NO_BRACE_ARGS },
00137   { "defoptx", cm_defun, NO_BRACE_ARGS },
00138   { "defopx", cm_defun, NO_BRACE_ARGS },
00139   { "defspec", cm_defun, NO_BRACE_ARGS },
00140   { "defspecx", cm_defun, NO_BRACE_ARGS },
00141   { "deftp", cm_defun, NO_BRACE_ARGS },
00142   { "deftpx", cm_defun, NO_BRACE_ARGS },
00143   { "deftypecv", cm_defun, NO_BRACE_ARGS },
00144   { "deftypecvx", cm_defun, NO_BRACE_ARGS },
00145   { "deftypefn", cm_defun, NO_BRACE_ARGS },
00146   { "deftypefnx", cm_defun, NO_BRACE_ARGS },
00147   { "deftypefun", cm_defun, NO_BRACE_ARGS },
00148   { "deftypefunx", cm_defun, NO_BRACE_ARGS },
00149   { "deftypeivar", cm_defun, NO_BRACE_ARGS },
00150   { "deftypeivarx", cm_defun, NO_BRACE_ARGS },
00151   { "deftypemethod", cm_defun, NO_BRACE_ARGS },
00152   { "deftypemethodx", cm_defun, NO_BRACE_ARGS },
00153   { "deftypeop", cm_defun, NO_BRACE_ARGS },
00154   { "deftypeopx", cm_defun, NO_BRACE_ARGS },
00155   { "deftypevar", cm_defun, NO_BRACE_ARGS },
00156   { "deftypevarx", cm_defun, NO_BRACE_ARGS },
00157   { "deftypevr", cm_defun, NO_BRACE_ARGS },
00158   { "deftypevrx", cm_defun, NO_BRACE_ARGS },
00159   { "defun", cm_defun, NO_BRACE_ARGS },
00160   { "defunx", cm_defun, NO_BRACE_ARGS },
00161   { "defvar", cm_defun, NO_BRACE_ARGS },
00162   { "defvarx", cm_defun, NO_BRACE_ARGS },
00163   { "defvr", cm_defun, NO_BRACE_ARGS },
00164   { "defvrx", cm_defun, NO_BRACE_ARGS },
00165   { "detailmenu", cm_detailmenu, NO_BRACE_ARGS },
00166   { "dfn", cm_dfn, BRACE_ARGS },
00167   { "dircategory", cm_dircategory, NO_BRACE_ARGS },
00168   { "direntry", cm_direntry, NO_BRACE_ARGS },
00169   { "display", cm_display, NO_BRACE_ARGS },
00170   { "dmn", cm_dmn, BRACE_ARGS },
00171   { "docbook", cm_docbook, NO_BRACE_ARGS },
00172   { "documentdescription", cm_documentdescription, NO_BRACE_ARGS },
00173   { "documentencoding", cm_documentencoding, NO_BRACE_ARGS },
00174   { "documentlanguage", cm_documentlanguage, NO_BRACE_ARGS },
00175   { "dotaccent", cm_accent, MAYBE_BRACE_ARGS },
00176   { "dotless", cm_dotless, BRACE_ARGS },
00177   { "dots", cm_dots, BRACE_ARGS },
00178   { "email", cm_email, BRACE_ARGS },
00179   { "emph", cm_emph, BRACE_ARGS },
00180   { "end", cm_end, NO_BRACE_ARGS },
00181   { "enddots", cm_enddots, BRACE_ARGS },
00182   { "enumerate", cm_enumerate, NO_BRACE_ARGS },
00183   { "env", cm_code, BRACE_ARGS },
00184   { "equiv", cm_equiv, BRACE_ARGS },
00185   { "error", cm_error, BRACE_ARGS },
00186   { "euro", cm_special_char, BRACE_ARGS },
00187   { "evenfooting", cm_ignore_line, NO_BRACE_ARGS },
00188   { "evenheading", cm_ignore_line, NO_BRACE_ARGS },
00189   { "everyfooting", cm_ignore_line, NO_BRACE_ARGS },
00190   { "everyheading", cm_ignore_line, NO_BRACE_ARGS },
00191   { "example", cm_example, NO_BRACE_ARGS },
00192   { "exampleindent", cm_exampleindent, NO_BRACE_ARGS },
00193   { "exclamdown", cm_special_char, BRACE_ARGS },
00194   { "exdent", cm_exdent, NO_BRACE_ARGS },
00195   { "expansion", cm_expansion, BRACE_ARGS },
00196   { "file", cm_code, BRACE_ARGS },
00197   { "finalout", cm_no_op, NO_BRACE_ARGS },
00198   { "findex", cm_findex, NO_BRACE_ARGS },
00199   { "firstparagraphindent", cm_firstparagraphindent, NO_BRACE_ARGS },
00200   { "float", cm_float, NO_BRACE_ARGS },
00201   { "flushleft", cm_flushleft, NO_BRACE_ARGS },
00202   { "flushright", cm_flushright, NO_BRACE_ARGS },
00203   { "footnote", cm_footnote, NO_BRACE_ARGS}, /* self-arg eater */
00204   { "footnotestyle", cm_footnotestyle, NO_BRACE_ARGS },
00205   { "format", cm_format, NO_BRACE_ARGS },
00206   { "ftable", cm_ftable, NO_BRACE_ARGS },
00207   { "group", cm_group, NO_BRACE_ARGS },
00208   { "heading", cm_heading, NO_BRACE_ARGS },
00209   { "headings", cm_ignore_line, NO_BRACE_ARGS },
00210   { "headitem", cm_headitem, NO_BRACE_ARGS },
00211   { "html", cm_html, NO_BRACE_ARGS },
00212   { "hyphenation", cm_ignore_arg, BRACE_ARGS },
00213   { "i", cm_i, BRACE_ARGS },
00214   { "ifclear", cm_ifclear, NO_BRACE_ARGS },
00215   { "ifeq", cm_ifeq, NO_BRACE_ARGS },
00216   { "ifdocbook", cm_ifdocbook, NO_BRACE_ARGS },
00217   { "ifhtml", cm_ifhtml, NO_BRACE_ARGS },
00218   { "ifinfo", cm_ifinfo, NO_BRACE_ARGS },
00219   { "ifnotdocbook", cm_ifnotdocbook, NO_BRACE_ARGS },
00220   { "ifnothtml", cm_ifnothtml, NO_BRACE_ARGS },
00221   { "ifnotinfo", cm_ifnotinfo, NO_BRACE_ARGS },
00222   { "ifnotplaintext", cm_ifnotplaintext, NO_BRACE_ARGS },
00223   { "ifnottex", cm_ifnottex, NO_BRACE_ARGS },
00224   { "ifnotxml", cm_ifnotxml, NO_BRACE_ARGS },
00225   { "ifplaintext", cm_ifplaintext, NO_BRACE_ARGS },
00226   { "ifset", cm_ifset, NO_BRACE_ARGS },
00227   { "iftex", cm_iftex, NO_BRACE_ARGS },
00228   { "ifxml", cm_ifxml, NO_BRACE_ARGS },
00229   { "ignore", command_name_condition, NO_BRACE_ARGS },
00230   { "image", cm_image, BRACE_ARGS },
00231   { "include", cm_include, NO_BRACE_ARGS },
00232   { "indent", cm_indent, NO_BRACE_ARGS },
00233   { "indicateurl", cm_indicate_url, BRACE_ARGS },
00234   { "inforef", cm_inforef, BRACE_ARGS },
00235   { "insertcopying", cm_insert_copying, NO_BRACE_ARGS },
00236   { "item", cm_item, NO_BRACE_ARGS },
00237   { "itemize", cm_itemize, NO_BRACE_ARGS },
00238   { "itemx", cm_itemx, NO_BRACE_ARGS },
00239   { "kbd", cm_kbd, BRACE_ARGS },
00240   { "kbdinputstyle", cm_ignore_line, NO_BRACE_ARGS },
00241   { "key", cm_key, BRACE_ARGS },
00242   { "kindex", cm_kindex, NO_BRACE_ARGS },
00243   { "l", cm_special_char, BRACE_ARGS },
00244   { "lisp", cm_lisp, NO_BRACE_ARGS },
00245   { "listoffloats", cm_listoffloats, NO_BRACE_ARGS },
00246   { "lowersections", cm_lowersections, NO_BRACE_ARGS },
00247   { "macro", cm_macro, NO_BRACE_ARGS },
00248   { "majorheading", cm_majorheading, NO_BRACE_ARGS },
00249   { "math", cm_math, BRACE_ARGS },
00250   { "menu", cm_menu, NO_BRACE_ARGS },
00251   { "minus", cm_minus, BRACE_ARGS },
00252   { "multitable", cm_multitable, NO_BRACE_ARGS },
00253   { "need", cm_ignore_line, NO_BRACE_ARGS },
00254   { "node", cm_node, NO_BRACE_ARGS },
00255   { "noindent", cm_noindent_cmd, NO_BRACE_ARGS },
00256   { "novalidate", cm_novalidate, NO_BRACE_ARGS },
00257   { "nwnode", cm_node, NO_BRACE_ARGS },
00258   { "o", cm_special_char, BRACE_ARGS },
00259   { "oddfooting", cm_ignore_line, NO_BRACE_ARGS },
00260   { "oddheading", cm_ignore_line, NO_BRACE_ARGS },
00261   { "oe", cm_special_char, BRACE_ARGS },
00262   { "option", cm_code, BRACE_ARGS },
00263   { "ordf", cm_special_char, BRACE_ARGS },
00264   { "ordm", cm_special_char, BRACE_ARGS },
00265   { "page", cm_no_op, NO_BRACE_ARGS },
00266   { "pagesizes", cm_ignore_line, NO_BRACE_ARGS },
00267   { "paragraphindent", cm_paragraphindent, NO_BRACE_ARGS },
00268   { "pindex", cm_pindex, NO_BRACE_ARGS },
00269   { "point", cm_point, BRACE_ARGS },
00270   { "pounds", cm_special_char, BRACE_ARGS },
00271   { "print", cm_print, BRACE_ARGS },
00272   { "printindex", cm_printindex, NO_BRACE_ARGS },
00273   { "pxref", cm_pxref, BRACE_ARGS },
00274   { "questiondown", cm_special_char, BRACE_ARGS },
00275   { "quotation", cm_quotation, NO_BRACE_ARGS },
00276   { "r", cm_r, BRACE_ARGS },
00277   { "raisesections", cm_raisesections, NO_BRACE_ARGS },
00278   { "ref", cm_ref, BRACE_ARGS },
00279   { "refill", cm_no_op, NO_BRACE_ARGS },
00280   { "registeredsymbol", cm_registeredsymbol, BRACE_ARGS },
00281   { "result", cm_result, BRACE_ARGS },
00282   { "ringaccent", cm_accent, MAYBE_BRACE_ARGS },
00283   { "rmacro", cm_rmacro, NO_BRACE_ARGS },
00284   { "samp", cm_code, BRACE_ARGS },
00285   { "sansserif", cm_sansserif, BRACE_ARGS },
00286   { "sc", cm_sc, BRACE_ARGS },
00287   { "section", cm_section, NO_BRACE_ARGS },
00288   { "set", cm_set, NO_BRACE_ARGS },
00289   { "setchapternewpage", cm_ignore_line, NO_BRACE_ARGS },
00290   { "setchapterstyle", cm_obsolete, NO_BRACE_ARGS },
00291   { "setcontentsaftertitlepage", cm_no_op, NO_BRACE_ARGS },
00292   { "setfilename", cm_setfilename, NO_BRACE_ARGS },
00293   { "setshortcontentsaftertitlepage", cm_no_op, NO_BRACE_ARGS },
00294   { "settitle", cm_settitle, NO_BRACE_ARGS },
00295   { "shortcaption", cm_caption, BRACE_ARGS },
00296   { "shortcontents", cm_contents, NO_BRACE_ARGS },
00297   { "shorttitlepage", cm_ignore_line, NO_BRACE_ARGS },
00298   { "slanted", cm_slanted, BRACE_ARGS },
00299   { "smallbook", cm_ignore_line, NO_BRACE_ARGS },
00300   { "smalldisplay", cm_smalldisplay, NO_BRACE_ARGS },
00301   { "smallexample", cm_smallexample, NO_BRACE_ARGS },
00302   { "smallformat", cm_smallformat, NO_BRACE_ARGS },
00303   { "smalllisp", cm_smalllisp, NO_BRACE_ARGS },
00304   { "sp", cm_sp, NO_BRACE_ARGS },
00305   { "ss", cm_special_char, BRACE_ARGS },
00306   { "strong", cm_strong, BRACE_ARGS },
00307   { "subheading", cm_subheading, NO_BRACE_ARGS },
00308   { "subsection", cm_subsection, NO_BRACE_ARGS },
00309   { "subsubheading", cm_subsubheading, NO_BRACE_ARGS },
00310   { "subsubsection", cm_subsubsection, NO_BRACE_ARGS },
00311   { "subtitle", cm_titlepage_cmds, NO_BRACE_ARGS },
00312   { "summarycontents", cm_contents, NO_BRACE_ARGS },
00313   { "syncodeindex", cm_synindex, NO_BRACE_ARGS },
00314   { "synindex", cm_synindex, NO_BRACE_ARGS },
00315   { "t", cm_tt, BRACE_ARGS },
00316   { "tab", cm_tab, NO_BRACE_ARGS },
00317   { "table", cm_table, NO_BRACE_ARGS },
00318   { "tex", cm_tex, NO_BRACE_ARGS },
00319   { "tie", cm_tie, BRACE_ARGS },
00320   { "tieaccent", cm_accent, MAYBE_BRACE_ARGS },
00321   { "tindex", cm_tindex, NO_BRACE_ARGS },
00322   { "title", cm_titlepage_cmds, NO_BRACE_ARGS },
00323   { "titlefont", cm_titlefont, BRACE_ARGS },
00324   { "titlepage", cm_titlepage, NO_BRACE_ARGS },
00325   { "today", cm_today, BRACE_ARGS },
00326   { "top", cm_top, NO_BRACE_ARGS  },
00327   { "u", cm_accent, MAYBE_BRACE_ARGS },
00328   { "ubaraccent", cm_accent, MAYBE_BRACE_ARGS },
00329   { "udotaccent", cm_accent, MAYBE_BRACE_ARGS },
00330   { "unmacro", cm_unmacro, NO_BRACE_ARGS },
00331   { "unnumbered", cm_unnumbered, NO_BRACE_ARGS },
00332   { "unnumberedsec", cm_unnumberedsec, NO_BRACE_ARGS },
00333   { "unnumberedsubsec", cm_unnumberedsubsec, NO_BRACE_ARGS },
00334   { "unnumberedsubsubsec", cm_unnumberedsubsubsec, NO_BRACE_ARGS },
00335   { "uref", cm_uref, BRACE_ARGS },
00336   { "url", cm_uref, BRACE_ARGS },
00337   { "v", cm_accent, MAYBE_BRACE_ARGS },
00338   { "value", cm_value, BRACE_ARGS },
00339   { "var", cm_var, BRACE_ARGS },
00340   { "verb", cm_verb, NO_BRACE_ARGS },
00341   { "verbatim", cm_verbatim, NO_BRACE_ARGS },
00342   { "verbatiminclude", cm_verbatiminclude, NO_BRACE_ARGS },
00343   { "vindex", cm_vindex, NO_BRACE_ARGS },
00344   { "vtable", cm_vtable, NO_BRACE_ARGS },
00345   { "vskip", cm_ignore_line, NO_BRACE_ARGS },
00346   { "w", cm_w, BRACE_ARGS },
00347   { "xml", cm_xml, NO_BRACE_ARGS },
00348   { "xref", cm_xref, BRACE_ARGS },
00349 
00350   /* Deprecated commands.  These used to be for italics.  */
00351   { "iappendix", cm_ideprecated, NO_BRACE_ARGS },
00352   { "iappendixsec", cm_ideprecated, NO_BRACE_ARGS },
00353   { "iappendixsection", cm_ideprecated, NO_BRACE_ARGS },
00354   { "iappendixsubsec", cm_ideprecated, NO_BRACE_ARGS },
00355   { "iappendixsubsubsec", cm_ideprecated, NO_BRACE_ARGS },
00356   { "ichapter", cm_ideprecated, NO_BRACE_ARGS },
00357   { "isection", cm_ideprecated, NO_BRACE_ARGS },
00358   { "isubsection", cm_ideprecated, NO_BRACE_ARGS },
00359   { "isubsubsection", cm_ideprecated, NO_BRACE_ARGS },
00360   { "iunnumbered", cm_ideprecated, NO_BRACE_ARGS },
00361   { "iunnumberedsec", cm_ideprecated, NO_BRACE_ARGS },
00362   { "iunnumberedsubsec", cm_ideprecated, NO_BRACE_ARGS },
00363   { "iunnumberedsubsubsec", cm_ideprecated, NO_BRACE_ARGS },
00364 
00365   /* Now @include does what this was used to. */
00366   { "infoinclude", cm_obsolete, NO_BRACE_ARGS },
00367   { "titlespec", cm_obsolete, NO_BRACE_ARGS },
00368 
00369   { NULL, NULL, NO_BRACE_ARGS }
00370 };
00371 
00372 /* The bulk of the Texinfo commands. */
00373 
00374 /* Commands which insert their own names. */
00375 void
00376 insert_self (int arg)
00377 {
00378   if (arg == START)
00379     add_word (command);
00380 }
00381 
00382 void
00383 insert_space (int arg)
00384 {
00385   if (arg == START)
00386     {
00387       if (xml && !docbook)
00388         xml_insert_entity ("space");
00389       else
00390         add_char (' ');
00391     }
00392 }
00393 
00394 /* Insert a comma.  Useful when a literal , would break our parsing of
00395    multiple arguments.  */
00396 void
00397 cm_comma (int arg)
00398 {
00399   if (arg == START)
00400     add_char (',');
00401 }
00402 
00403 
00404 /* Force a line break in the output. */
00405 void
00406 cm_asterisk (void)
00407 {
00408   if (html)
00409     add_word ("<br>");
00410   else if (xml && !docbook)
00411     xml_insert_entity ("linebreak");
00412   else if (docbook) 
00413     xml_asterisk ();
00414   else
00415     {
00416       close_single_paragraph ();
00417       cm_noindent ();
00418     }
00419 }
00420 
00421 /* Insert ellipsis. */
00422 void
00423 cm_dots (int arg)
00424 {
00425   if (arg == START)
00426     {
00427       if (xml && !docbook)
00428         xml_insert_entity ("dots");
00429       else if (docbook)
00430         xml_insert_entity ("hellip");
00431       else
00432        if (html && !in_fixed_width_font)
00433          insert_string ("<small class=\"dots\">...</small>");
00434        else
00435          add_word ("...");
00436     }
00437 }
00438 
00439 /* Insert ellipsis for sentence end. */
00440 void
00441 cm_enddots (int arg)
00442 {
00443   if (arg == START)
00444     {
00445       if (xml && !docbook)
00446        xml_insert_entity ("enddots");
00447       else if (docbook)
00448        {
00449          xml_insert_entity ("hellip");
00450          add_char ('.');
00451        }
00452       else
00453        if (html && !in_fixed_width_font)
00454          insert_string ("<small class=\"enddots\">....</small>");
00455        else
00456          add_word ("....");
00457     }
00458 }
00459 
00460 void
00461 cm_bullet (int arg)
00462 {
00463   if (arg == START)
00464     {
00465       if (html)
00466         add_word ("&bull;");
00467       else if (xml && !docbook)
00468        xml_insert_entity ("bullet");
00469       else if (docbook)
00470        xml_insert_entity ("bull");
00471       else
00472         add_char ('*');
00473     }
00474 }
00475 
00476 void
00477 cm_minus (int arg)
00478 {
00479   if (arg == START)
00480     {
00481       if (xml)
00482        xml_insert_entity ("minus");
00483       else if (html)
00484         add_word ("&minus;");
00485       else
00486        add_char ('-');
00487     }
00488 }
00489 
00490 /* Formatting a dimension unit.  */
00491 void
00492 cm_dmn (int arg)
00493 {
00494   if (html)
00495     insert_html_tag_with_attribute (arg, "span", "class=\"dmn\"");
00496   else if (docbook)
00497     /* No units in docbook yet.  */
00498     ;
00499   else if (xml)
00500     xml_insert_element (DIMENSION, arg);
00501 }
00502 
00503 /* Insert "TeX". */
00504 void
00505 cm_TeX (int arg)
00506 {
00507   static int last_position;
00508 
00509   if (arg == START)
00510     {
00511       if (xml)
00512        xml_insert_entity ("tex");
00513       else
00514        add_word ("TeX");
00515 
00516       last_position = output_paragraph_offset;
00517     }
00518   else if (last_position != output_paragraph_offset)
00519     {
00520       warning (_("arguments to @%s ignored"), command);
00521       output_paragraph_offset = last_position;
00522     }
00523 }
00524 
00525 /* Insert "LaTeX".  */
00526 void
00527 cm_LaTeX (int arg)
00528 {
00529   static int last_position;
00530 
00531   if (arg == START)
00532     {
00533       if (xml)
00534         xml_insert_entity ("latex");
00535       else
00536         add_word ("LaTeX");
00537 
00538       last_position = output_paragraph_offset;
00539     }
00540   else if (last_position != output_paragraph_offset)
00541     {
00542       warning (_("arguments to @%s ignored"), command);
00543       output_paragraph_offset = last_position;
00544     }
00545 }
00546 
00547 /* Copyright symbol.  */
00548 void
00549 cm_copyright (int arg)
00550 {
00551   if (arg == START)
00552     {
00553     if (html)
00554       add_word ("&copy;");
00555     else if (xml && !docbook)
00556       xml_insert_entity ("copyright");
00557     else if (docbook)
00558       xml_insert_entity ("copy");
00559     else
00560       add_word ("(C)");
00561     }
00562 }
00563 
00564 /* Registered symbol.  */
00565 void
00566 cm_registeredsymbol (int arg)
00567 {
00568   if (arg == START)
00569     {
00570       if (html)
00571         add_word ("&reg;");
00572       else if (docbook)
00573         xml_insert_entity ("reg");
00574       else if (xml && !docbook)
00575         xml_insert_entity ("registered");
00576       else
00577         add_word ("(R)");
00578     }
00579 }
00580 
00581 void
00582 cm_today (int arg)
00583 {
00584   static char *months[12] =
00585     { N_("January"), N_("February"), N_("March"), N_("April"), N_("May"),
00586       N_("June"), N_("July"), N_("August"), N_("September"), N_("October"),
00587       N_("November"), N_("December") };
00588   if (arg == START)
00589     {
00590       time_t timer = time (0);
00591       struct tm *ts = localtime (&timer);
00592       add_word_args ("%d %s %d", ts->tm_mday, _(months[ts->tm_mon]),
00593                      ts->tm_year + 1900);
00594     }
00595 }
00596 
00597 void
00598 cm_comment (void)
00599 {
00600   /* For HTML, do not output comments before HTML header is written,
00601      otherwise comments before @settitle cause an empty <title> in the
00602      header.  */
00603   if ((html && html_output_head_p) || xml)
00604     {
00605       char *line;
00606       get_rest_of_line (0, &line);
00607 
00608       if (strlen (line) > 0)
00609         {
00610           int save_inhibit_indentation = inhibit_paragraph_indentation;
00611           int save_paragraph_is_open = paragraph_is_open;
00612           int save_escape_html = escape_html;
00613           int save_xml_no_para = xml_no_para;
00614           int i;
00615 
00616           inhibit_paragraph_indentation = 1;
00617           escape_html = 0;
00618           xml_no_para = 1;
00619 
00620           /* @c and @comment can appear between @item and @itemx,
00621              @deffn and @deffnx.  */
00622           xml_dont_touch_items_defs++;
00623 
00624           /* Use insert for HTML, and XML when indentation is enabled.
00625              For Docbook, use add_char.  */
00626           if (xml && xml_indentation_increment > 0
00627               && output_paragraph[output_paragraph_offset-1] != '\n')
00628             insert ('\n');
00629 
00630           /* Crunch double hyphens in comments.  */
00631           add_html_block_elt ("<!-- ");
00632           for (i = 0; i < strlen (line); i++)
00633             if (line[i] != '-' || (i && line[i-1] != '-'))
00634               add_char (line[i]);
00635           add_word (" -->");
00636 
00637           if (html)
00638             add_char ('\n');
00639 
00640           inhibit_paragraph_indentation = save_inhibit_indentation;
00641           paragraph_is_open = save_paragraph_is_open;
00642           escape_html = save_escape_html;
00643           xml_no_para = save_xml_no_para;
00644           xml_dont_touch_items_defs--;
00645         }
00646 
00647       free (line);
00648     }
00649   else
00650     cm_ignore_line ();
00651 }
00652 
00653 
00654 
00655 /* We keep acronyms with two arguments around, to be able to refer to them
00656    later with only one argument.  */
00657 static ACRONYM_DESC *acronyms_stack = NULL;
00658 
00659 static void
00660 cm_acronym_or_abbr (int arg, int is_abbr)
00661 {
00662   char *aa, *description;
00663   unsigned len;
00664 
00665   /* We do everything at START.  */
00666   if (arg == END)
00667     return;
00668 
00669   get_until_in_braces (",", &aa);
00670   if (input_text[input_text_offset] == ',')
00671     input_text_offset++;
00672   get_until_in_braces ("}", &description);
00673 
00674   canon_white (aa);
00675   canon_white (description);
00676 
00677   /* If not enclosed in braces, strip after comma to be compatible
00678      with texinfo.tex.  */
00679   if (description[0] != '{' && strchr (description, ',') != NULL)
00680     {
00681       int i = 0;
00682       while (description[i] != ',')
00683         i++;
00684       /* For now, just terminate the string at comma.  */
00685       description[i] = 0;
00686     }
00687 
00688   /* Get description out of braces.  */
00689   if (description[0] == '{')
00690     description++;
00691 
00692   len = strlen (description);
00693   if (len && description[len-1] == '}')
00694     description[len-1] = 0;
00695 
00696   /* Save new description.  */
00697   if (strlen (description) > 0)
00698     {
00699       ACRONYM_DESC *new = xmalloc (sizeof (ACRONYM_DESC));
00700 
00701       new->acronym = xstrdup (aa);
00702       new->description = xstrdup (description);
00703       new->next = acronyms_stack;
00704       acronyms_stack = new;
00705     }
00706 
00707   if (html)
00708     {
00709       add_word (is_abbr ? "<abbr" : "<acronym");
00710 
00711       if (strlen (description) > 0)
00712         add_word_args (" title=\"%s\"", text_expansion (description));
00713       else if (acronyms_stack)
00714         {
00715           /* No second argument, get from previous.  Search order is from
00716              last to first defined, so we get the most recent version of
00717              the description.  */
00718           ACRONYM_DESC *temp = acronyms_stack;
00719 
00720           while (temp)
00721             {
00722               if (STREQ (aa, temp->acronym)
00723                   && strlen (temp->description) > 0)
00724                 {
00725                   add_word_args (" title=\"%s\"",
00726                                  text_expansion (temp->description));
00727                   break;
00728                 }
00729               temp = temp->next;
00730             }
00731         }
00732 
00733       add_char ('>');
00734       execute_string ("%s", aa);
00735       add_word (is_abbr ? "</abbr>" : "</acronym>");
00736     }
00737   else if (docbook)
00738     {
00739       xml_insert_element (is_abbr ? ABBREV : ACRONYM, START);
00740       execute_string ("%s", aa);
00741       xml_insert_element (is_abbr ? ABBREV : ACRONYM, END);
00742     }
00743   else if (xml)
00744     {
00745       xml_insert_element (is_abbr ? ABBREV : ACRONYM, START);
00746 
00747       xml_insert_element (is_abbr ? ABBREVWORD : ACRONYMWORD, START);
00748       execute_string ("%s", aa);
00749       xml_insert_element (is_abbr ? ABBREVWORD : ACRONYMWORD, END);
00750 
00751       if (strlen (description) > 0)
00752         {
00753           xml_insert_element (is_abbr ? ABBREVDESC : ACRONYMDESC, START);
00754           execute_string ("%s", description);
00755           xml_insert_element (is_abbr ? ABBREVDESC : ACRONYMDESC, END);
00756         }
00757 
00758       xml_insert_element (is_abbr ? ABBREV : ACRONYM, END);
00759     }
00760   else
00761     execute_string ("%s", aa);
00762 
00763   /* Put description into parenthesis after the acronym for all outputs
00764      except XML.  */
00765   if (strlen (description) > 0 && (!xml || docbook))
00766     add_word_args (" (%s)", description);
00767 }
00768 
00769 void
00770 cm_acronym (int arg)
00771 {
00772   cm_acronym_or_abbr (arg, 0);
00773 }
00774 
00775 void
00776 cm_abbr (int arg)
00777 {
00778   cm_acronym_or_abbr (arg, 1);
00779 }
00780 
00781 void
00782 cm_tt (int arg)
00783 {
00784   /* @t{} is a no-op in Info.  */
00785   if (html)
00786     insert_html_tag (arg, "tt");
00787   else if (xml)
00788     xml_insert_element (TT, arg);
00789 }
00790 
00791 void
00792 cm_code (int arg)
00793 {
00794   if (arg == START)
00795     in_fixed_width_font++;
00796 
00797   if (xml)
00798     {
00799       if (STREQ (command, "command"))
00800        xml_insert_element (COMMAND_TAG, arg);
00801       else if (STREQ (command, "env"))
00802        xml_insert_element (ENV, arg);
00803       else if (STREQ (command, "file"))
00804        xml_insert_element (FILE_TAG, arg);
00805       else if (STREQ (command, "option"))
00806        xml_insert_element (OPTION, arg);
00807       else if (STREQ (command, "samp"))
00808         {
00809           if (docbook && arg == START)
00810             {
00811               /* Even though @samp is in_fixed_width_font, it
00812                  should always start a paragraph.  Unfortunately,
00813                  in_fixed_width_font inhibits that.  */
00814               xml_start_para ();
00815               xml_insert_entity ("lsquo");
00816             }
00817           xml_insert_element (SAMP, arg);
00818           if (docbook && arg == END)
00819             xml_insert_entity ("rsquo");
00820         }
00821       else
00822        xml_insert_element (CODE, arg);
00823     }
00824   else if (html)
00825     {
00826       if (STREQ (command, "code"))
00827         insert_html_tag (arg, "code");
00828       else
00829         { /* Use <samp> tag in general to get typewriter.  */
00830           if (arg == START)
00831             { /* If @samp specifically, add quotes a la TeX output.  */
00832               if (STREQ (command, "samp")) add_char ('`');
00833               add_word ("<samp>");
00834             }
00835           insert_html_tag_with_attribute (arg, "span", "class=\"%s\"",command);
00836           if (arg == END)
00837             {
00838               add_word ("</samp>");
00839               if (STREQ (command, "samp")) add_char ('\'');
00840             }
00841         }
00842     }
00843   else
00844     {
00845       extern int printing_index;
00846 
00847       if (!printing_index)
00848         {
00849           if (arg == START)
00850             add_char ('`');
00851           else
00852             add_meta_char ('\'');
00853         }
00854     }
00855 }
00856 
00857 void
00858 cm_kbd (int arg)
00859 {
00860   if (xml)
00861     xml_insert_element (KBD, arg);
00862   else if (html)
00863     { /* Seems like we should increment in_fixed_width_font for Info
00864          format too, but then the quote-omitting special case gets
00865          confused.  Punt.  */
00866       if (arg == START)
00867         in_fixed_width_font++;
00868       insert_html_tag (arg, "kbd");
00869     }
00870   else
00871     { /* People use @kbd in an example to get the "user input" font.
00872          We don't want quotes in that case.  */
00873       if (!in_fixed_width_font)
00874         cm_code (arg);
00875     }
00876 }
00877 
00878 /* Just show a url (http://example.org/..., for example), don't link to it.  */
00879 void
00880 cm_indicate_url (int arg, int start, int end)
00881 {
00882   if (xml)
00883     xml_insert_element (URL, arg);
00884   else if (html)
00885     {
00886       if (arg == START)
00887         add_word ("&lt;");
00888       insert_html_tag (arg, "code");
00889       if (arg != START)
00890         add_word ("&gt;");
00891     }
00892   else
00893     if (arg == START)
00894       add_word ("<");
00895     else
00896       add_word (">");
00897 }
00898 
00899 void
00900 cm_key (int arg)
00901 {
00902   if (xml)
00903     xml_insert_element (KEY, arg);
00904   else if (html)
00905     add_word (arg == START ? "&lt;" : "&gt;");
00906   else
00907     add_char (arg == START ? '<' : '>');
00908 }
00909 
00910 /* Handle a command that switches to a non-fixed-width font.  */
00911 void
00912 not_fixed_width (int arg)
00913 {
00914   if (arg == START)
00915     in_fixed_width_font = 0;
00916 }
00917 
00918 /* @var in makeinfo just uppercases the text. */
00919 void
00920 cm_var (int arg, int start_pos, int end_pos)
00921 {
00922   if (xml)
00923     xml_insert_element (VAR, arg);
00924   else
00925     {
00926   not_fixed_width (arg);
00927 
00928   if (html)
00929     insert_html_tag (arg, "var");
00930   else if (arg == END)
00931     {
00932       while (start_pos < end_pos)
00933         {
00934           unsigned char c = output_paragraph[start_pos];
00935           if (strchr ("[](),", c))
00936             warning (_("unlikely character %c in @var"), c);
00937           output_paragraph[start_pos] = coerce_to_upper (c);
00938           start_pos++;
00939         }
00940     }
00941     }
00942 }
00943 
00944 void
00945 cm_sc (int arg, int start_pos, int end_pos)
00946 {
00947   if (xml)
00948     xml_insert_element (SC, arg);
00949   else
00950     {
00951       not_fixed_width (arg);
00952 
00953       if (arg == START)
00954         {
00955           if (html)
00956             insert_html_tag_with_attribute (arg, "span", "class=\"sc\"");
00957         }
00958       else
00959         {
00960           int all_upper;
00961 
00962           if (html)
00963             start_pos += sizeof ("<span class=\"sc\">") - 1; /* skip <span> */
00964 
00965           /* Avoid the warning below if there's no text inside @sc{}, or
00966              when processing menus under --no-headers.  */
00967           all_upper = start_pos < end_pos;
00968 
00969           while (start_pos < end_pos)
00970             {
00971               unsigned char c = output_paragraph[start_pos];
00972               if (!isupper (c))
00973                 all_upper = 0;
00974               if (!html)
00975                 output_paragraph[start_pos] = coerce_to_upper (c);
00976               start_pos++;
00977             }
00978           if (all_upper)
00979             warning (_("@sc argument all uppercase, thus no effect"));
00980 
00981           if (html)
00982             insert_html_tag (arg, "span");
00983         }
00984     }
00985 }
00986 
00987 void
00988 cm_dfn (int arg, int position)
00989 {
00990   if (xml)
00991     xml_insert_element (DFN, arg);
00992   else
00993     {
00994   if (html)
00995     insert_html_tag (arg, "dfn");
00996   else if (arg == START)
00997     add_char ('"');
00998   else
00999     add_meta_char ('"');
01000     }
01001 }
01002 
01003 void
01004 cm_emph (int arg)
01005 {
01006   if (xml)
01007     xml_insert_element (EMPH, arg);
01008   else if (html)
01009     insert_html_tag (arg, "em");
01010   else
01011     add_char ('_');
01012 }
01013 
01014 void
01015 cm_verb (int arg)
01016 {
01017   int character;
01018   int delimiter = 0; /* avoid warning */
01019   int seen_end = 0;
01020 
01021   in_fixed_width_font++;
01022   /* are these necessary ? */
01023   last_char_was_newline = 0;
01024 
01025   if (html)
01026     add_word ("<tt>");
01027 
01028   if (input_text_offset < input_text_length)
01029     {
01030       character = curchar ();
01031       if (character == '{')
01032        input_text_offset++;
01033       else
01034        line_error (_("`{' expected, but saw `%c'"), character);
01035     }
01036     
01037   if (input_text_offset < input_text_length)
01038     {
01039       delimiter = curchar ();
01040       input_text_offset++;
01041     }
01042 
01043   while (input_text_offset < input_text_length)
01044     {
01045       character = curchar ();
01046 
01047       if (character == '\n')
01048         {
01049           line_number++;
01050           if (html)
01051             add_word ("<br>\n");
01052         }
01053 
01054       else if (html && character == '<')
01055         add_word ("&lt;");
01056 
01057       else if (html && character == '&')
01058         add_word ("&amp;");
01059 
01060       else if (character == delimiter && input_text[input_text_offset+1] == '}')
01061        { /* Assume no newlines in END_VERBATIM. */
01062          seen_end = 1;
01063          input_text_offset++;
01064          break;
01065        }
01066 
01067       else
01068         add_char (character);
01069 
01070       input_text_offset++;
01071     }
01072 
01073   if (!seen_end)
01074     warning (_("end of file inside verb block"));
01075   
01076   if (input_text_offset < input_text_length)
01077     {
01078       character = curchar ();
01079       if (character == '}')
01080        input_text_offset++;
01081       else
01082        line_error (_("`}' expected, but saw `%c'"), character);
01083     }
01084 
01085   if (html)
01086     add_word ("</tt>");
01087 
01088   in_fixed_width_font--;
01089 }
01090 
01091 
01092 void
01093 cm_strong (int arg, int start_pos, int end_pos)
01094 {
01095   if (docbook && arg == START)
01096     xml_insert_element_with_attribute (B, arg, "role=\"bold\"");
01097   else if (xml)
01098     xml_insert_element (STRONG, arg);
01099   else if (html)
01100     insert_html_tag (arg, "strong");
01101   else
01102     add_char ('*');
01103   
01104   if (!xml && !html && !docbook && !no_headers
01105       && arg == END
01106       && end_pos - start_pos >= 6
01107       && (STRNCASEEQ ((char *) output_paragraph + start_pos, "*Note:", 6)
01108           || STRNCASEEQ ((char *) output_paragraph + start_pos, "*Note ", 6)))
01109     {
01110       /* Translators: "Note:" is literal here and should not be
01111          translated.  @strong{Nota}, say, does not cause the problem.  */
01112       warning (_("@strong{Note...} produces a spurious cross-reference in Info; reword to avoid that"));
01113       /* Adjust the output to avoid writing the bad xref.  */
01114       output_paragraph[start_pos + 5] = '_';
01115     }
01116 }
01117 
01118 void
01119 cm_cite (int arg, int position)
01120 {
01121   if (xml)
01122     xml_insert_element (CITE, arg);        
01123   else if (html)
01124     insert_html_tag (arg, "cite");
01125   else
01126     {
01127       if (arg == START)
01128         add_char ('`');
01129       else
01130         add_char ('\'');
01131     }
01132 }
01133 
01134 /* No highlighting, but argument switches fonts.  */
01135 void
01136 cm_not_fixed_width (int arg, int start, int end)
01137 {
01138   if (xml)
01139     xml_insert_element (NOTFIXEDWIDTH, arg);
01140   not_fixed_width (arg);
01141 }
01142 
01143 void
01144 cm_i (int arg)
01145 {
01146   /* Make use of <lineannotation> of Docbook, if we are
01147      inside an @example or similar.  */
01148   extern int printing_index;
01149   if (docbook && !filling_enabled && !printing_index)
01150     xml_insert_element (LINEANNOTATION, arg);
01151   else if (xml)
01152     xml_insert_element (I, arg);
01153   else if (html)
01154     insert_html_tag (arg, "i");
01155   else
01156     not_fixed_width (arg);
01157 }
01158 
01159 void
01160 cm_slanted (int arg)
01161 {
01162   /* Make use of <lineannotation> of Docbook, if we are
01163      inside an @example or similar.  */
01164   extern int printing_index;
01165   if (docbook && !filling_enabled && !printing_index)
01166     xml_insert_element (LINEANNOTATION, arg);
01167   else if (xml)
01168     xml_insert_element (SLANTED, arg);
01169   else if (html)
01170     insert_html_tag (arg, "i");
01171   else
01172     not_fixed_width (arg);
01173 }
01174 
01175 void
01176 cm_b (int arg)
01177 {
01178   /* See cm_i comments.  */
01179   extern int printing_index;
01180   if (docbook && !filling_enabled && !printing_index)
01181     xml_insert_element (LINEANNOTATION, arg);
01182   else if (docbook && arg == START)
01183     xml_insert_element_with_attribute (B, arg, "role=\"bold\"");
01184   else if (xml)
01185     xml_insert_element (B, arg);
01186   else if (html)
01187     insert_html_tag (arg, "b");
01188   else
01189     not_fixed_width (arg);
01190 }
01191 
01192 void
01193 cm_r (int arg)
01194 {
01195   /* See cm_i comments.  */
01196   extern int printing_index;
01197   if (docbook && !filling_enabled && !printing_index)
01198     xml_insert_element (LINEANNOTATION, arg);
01199   else if (xml)
01200     xml_insert_element (R, arg);
01201   else if (html)
01202     insert_html_tag_with_attribute (arg, "span", "class=\"roman\"");
01203   else
01204     not_fixed_width (arg);
01205 }
01206 
01207 void
01208 cm_sansserif (int arg)
01209 {
01210   /* See cm_i comments.  */
01211   extern int printing_index;
01212   if (docbook && !filling_enabled && !printing_index)
01213     xml_insert_element (LINEANNOTATION, arg);
01214   else if (xml)
01215     xml_insert_element (SANSSERIF, arg);
01216   else if (html)
01217     insert_html_tag_with_attribute (arg, "span", "class=\"sansserif\"");
01218   else
01219     not_fixed_width (arg);
01220 }
01221 
01222 void
01223 cm_titlefont (int arg)
01224 {
01225   if (xml)
01226     xml_insert_element (TITLEFONT, arg);
01227   else
01228    {
01229      not_fixed_width (arg);
01230      if (html)
01231        {
01232          html_title_written = 1; /* suppress title from @settitle */
01233          if (arg == START)
01234            add_word ("<h1 class=\"titlefont\">");
01235          else
01236            add_word ("</h1>\n");
01237        }
01238    }
01239 }
01240 
01241 
01242 /* Unfortunately, we cannot interpret @math{} contents like TeX does.  We just
01243    pass them through.  */
01244 void
01245 cm_math (int arg)
01246 {
01247   if (xml && !docbook)
01248     xml_insert_element (MATH, arg);
01249 }
01250 
01251 /* Various commands are no-op's. */
01252 void
01253 cm_no_op (void)
01254 {
01255 }
01256 
01257 
01258 /* For proofing single chapters, etc.  */
01259 void
01260 cm_novalidate (void)
01261 {
01262   validating = 0;
01263 }
01264 
01265 
01266 /* Prevent the argument from being split across two lines. */
01267 void
01268 cm_w (int arg)
01269 {
01270   if (arg == START)
01271     non_splitting_words++;
01272   else
01273     {
01274       if (docbook || html || xml)
01275         /* This is so @w{$}Log$ doesn't end up as <dollar>Log<dollar>
01276            in the output.  */
01277         insert_string ("<!-- /@w -->");
01278         
01279       non_splitting_words--;
01280     }
01281 }
01282 
01283 
01284 /* An unbreakable word space.  Same as @w{ } for makeinfo, but different
01285    for TeX (the space stretches and stretches, and does not inhibit
01286    hyphenation).  */
01287 void
01288 cm_tie (int arg)
01289 {
01290   if (arg == START)
01291     {
01292       cm_w (START);
01293       add_char (' ');
01294     }
01295   else
01296     cm_w (END);
01297 }
01298 
01299 /* Explain that this command is obsolete, thus the user shouldn't
01300    do anything with it. */
01301 static void
01302 cm_obsolete (int arg, int start, int end)
01303 {
01304   if (arg == START)
01305     warning (_("%c%s is obsolete"), COMMAND_PREFIX, command);
01306 }
01307 
01308 
01309 /* Inhibit the indentation of the next paragraph, but not of following
01310    paragraphs.  */
01311 void
01312 cm_noindent (void)
01313 {
01314   if (!inhibit_paragraph_indentation)
01315     inhibit_paragraph_indentation = -1;
01316 }
01317 
01318 void
01319 cm_noindent_cmd (void)
01320 {
01321   cm_noindent ();
01322   xml_no_indent = 1;
01323   skip_whitespace_and_newlines();
01324 
01325   if (xml)
01326     xml_start_para ();
01327   else if (html && !paragraph_is_open)
01328     add_html_block_elt ("<p class=\"noindent\">");
01329   else
01330     {
01331       paragraph_is_open = 0;
01332       start_paragraph ();
01333     }
01334 }
01335 
01336 /* Force indentation of the next paragraph. */
01337 void
01338 cm_indent (void)
01339 {
01340   inhibit_paragraph_indentation = 0;
01341   xml_no_indent = 0;
01342   skip_whitespace_and_newlines();
01343   
01344   if (xml)
01345     xml_start_para ();
01346   else if (html && !paragraph_is_open)
01347     add_html_block_elt ("<p class=\"indent\">");
01348   else
01349     start_paragraph ();
01350 }
01351 
01352 /* I don't know exactly what to do with this.  Should I allow
01353    someone to switch filenames in the middle of output?  Since the
01354    file could be partially written, this doesn't seem to make sense.
01355    Another option: ignore it, since they don't really want to
01356    switch files.  Finally, complain, or at least warn.  It doesn't
01357    really matter, anyway, since this doesn't get executed.  */
01358 void
01359 cm_setfilename (void)
01360 {
01361   char *filename;
01362   get_rest_of_line (1, &filename);
01363   /* warning ("`@%s %s' encountered and ignored", command, filename); */
01364   if (xml)
01365     add_word_args ("<setfilename>%s</setfilename>", filename);
01366   free (filename);
01367 }
01368 
01369 void
01370 cm_settitle (void)
01371 {
01372   if (xml)
01373     {
01374       xml_begin_document (current_output_filename);
01375       xml_insert_element (SETTITLE, START);
01376       xml_in_book_title = 1;
01377       get_rest_of_line (0, &title);
01378       execute_string ("%s", title);
01379       xml_in_book_title = 0;
01380       xml_insert_element (SETTITLE, END);
01381     }
01382   else
01383     get_rest_of_line (0, &title);
01384 }
01385 
01386 
01387 /* Ignore argument in braces.  */
01388 void
01389 cm_ignore_arg (int arg, int start_pos, int end_pos)
01390 {
01391   if (arg == END)
01392     output_paragraph_offset = start_pos;
01393 }
01394 
01395 /* Ignore argument on rest of line.  */
01396 void
01397 cm_ignore_line (void)
01398 {
01399   discard_until ("\n");
01400 }
01401 
01402 /* Insert the number of blank lines passed as argument. */
01403 void
01404 cm_sp (void)
01405 {
01406   int lines;
01407   char *line;
01408 
01409   /* Due to tricky stuff in execute_string(), @value{} can't be expanded.
01410      So there is really no reason to enable expansion for @sp parameters.  */
01411   get_rest_of_line (0, &line);
01412 
01413   if (sscanf (line, "%d", &lines) != 1 || lines <= 0)
01414     line_error (_("@sp requires a positive numeric argument, not `%s'"), line);
01415   else
01416     {
01417       if (xml)
01418        {
01419           /* @sp can appear between @item and @itemx, @deffn and @deffnx.  */
01420           xml_dont_touch_items_defs++;
01421          xml_insert_element_with_attribute (SP, START, "lines=\"%s\"", line);
01422          /*     insert_string (line);*/
01423          xml_insert_element (SP, END);
01424           xml_dont_touch_items_defs--;
01425        }
01426       else
01427         {
01428           /* Must disable filling since otherwise multiple newlines is like
01429              multiple spaces.  Must close paragraph since that's what the
01430              manual says and that's what TeX does.  */
01431           int save_filling_enabled = filling_enabled;
01432           filling_enabled = 0;
01433 
01434           /* close_paragraph generates an extra blank line.  */
01435           close_single_paragraph ();
01436 
01437           if (lines && html && !executing_string)
01438             html_output_head ();
01439 
01440           if (html)
01441             add_html_block_elt ("<pre class=\"sp\">\n");
01442 
01443           while (lines--)
01444             add_char ('\n');
01445 
01446           if (html)
01447             add_html_block_elt ("</pre>\n");
01448 
01449           filling_enabled = save_filling_enabled;
01450         }
01451     }
01452   free (line);
01453 }
01454 
01455 /* @dircategory LINE outputs INFO-DIR-SECTION LINE, unless --no-headers.  */ 
01456 void
01457 cm_dircategory (void)
01458 {
01459   char *line;
01460 
01461   if (html || docbook)
01462     cm_ignore_line ();
01463   else if (xml)
01464     {
01465       xml_insert_element (DIRCATEGORY, START);
01466       get_rest_of_line (1, &line);
01467       insert_string (line);
01468       free (line);
01469       xml_insert_element (DIRCATEGORY, END);
01470     }
01471   else
01472     {
01473       get_rest_of_line (1, &line);
01474 
01475       if (!no_headers && !html)
01476         {
01477           kill_self_indent (-1); /* make sure there's no indentation */
01478           insert_string ("INFO-DIR-SECTION ");
01479           insert_string (line);
01480           insert ('\n');
01481         }
01482 
01483       free (line);
01484     }
01485 }
01486 
01487 /* Start a new line with just this text on it.
01488    Then center the line of text.
01489    */
01490 void
01491 cm_center (void)
01492 {
01493   if (xml)
01494     {
01495       char *line;
01496       xml_insert_element (CENTER, START);
01497       get_rest_of_line (0, &line);
01498       execute_string ("%s", line);
01499       free (line);
01500       xml_insert_element (CENTER, END);
01501     }
01502   else
01503     {
01504       int i, start, length;
01505       char *line;
01506       int save_indented_fill = indented_fill;
01507       int save_filling_enabled = filling_enabled;
01508       int fudge_factor = 1;
01509 
01510       filling_enabled = indented_fill = 0;
01511       cm_noindent ();
01512       start = output_paragraph_offset;
01513 
01514       if (html)
01515         add_html_block_elt ("<div align=\"center\">");
01516 
01517       inhibit_output_flushing ();
01518       get_rest_of_line (0, &line);
01519       execute_string ("%s", line);
01520       free (line);
01521       uninhibit_output_flushing ();
01522       if (html)
01523         add_html_block_elt ("</div>");
01524 
01525        else
01526          {
01527            i = output_paragraph_offset - 1;
01528            while (i > (start - 1) && output_paragraph[i] == '\n')
01529              i--;
01530 
01531            output_paragraph_offset = ++i;
01532            length = output_paragraph_offset - start;
01533 
01534            if (length < (fill_column - fudge_factor))
01535              {
01536                line = xmalloc (1 + length);
01537                memcpy (line, (char *)(output_paragraph + start), length);
01538 
01539                i = (fill_column - fudge_factor - length) / 2;
01540                output_paragraph_offset = start;
01541 
01542                while (i--)
01543                  insert (' ');
01544 
01545                for (i = 0; i < length; i++)
01546                  insert (line[i]);
01547 
01548                free (line);
01549              }
01550          }
01551 
01552       insert ('\n');
01553       filling_enabled = save_filling_enabled;
01554       indented_fill = save_indented_fill;
01555       close_single_paragraph ();
01556       if (looking_at("\n"))
01557         insert ('\n');
01558     }
01559 }
01560 
01561 /* Show what an expression returns. */
01562 void
01563 cm_result (int arg)
01564 {
01565   if (arg == END)
01566     add_word (html ? "=&gt;" : "=>");
01567 }
01568 
01569 /* What an expression expands to. */
01570 void
01571 cm_expansion (int arg)
01572 {
01573   if (arg == END)
01574     add_word (html ? "==&gt;" : "==>");
01575 }
01576 
01577 /* Indicates two expressions are equivalent. */
01578 void
01579 cm_equiv (int arg)
01580 {
01581   if (arg == END)
01582     add_word ("==");
01583 }
01584 
01585 /* What an expression may print. */
01586 void
01587 cm_print (int arg)
01588 {
01589   if (arg == END)
01590     add_word ("-|");
01591 }
01592 
01593 /* An error signaled. */
01594 void
01595 cm_error (int arg)
01596 {
01597   if (arg == END)
01598     add_word (html ? "error--&gt;" : "error-->");
01599 }
01600 
01601 /* The location of point in an example of a buffer. */
01602 void
01603 cm_point (int arg)
01604 {
01605   if (arg == END)
01606     add_word ("-!-");
01607 }
01608 
01609 /* @exdent: Start a new line with just this text on it.
01610    The text is outdented one level if possible. */
01611 void
01612 cm_exdent (void)
01613 {
01614   char *line;
01615   int save_indent = current_indent;
01616   int save_in_fixed_width_font = in_fixed_width_font;
01617 
01618   /* Read argument.  */
01619   get_rest_of_line (0, &line);
01620 
01621   /* Exdent the output.  Actually this may be a no-op.   */
01622   if (current_indent)
01623     current_indent -= default_indentation_increment;
01624 
01625   /* @exdent arg is supposed to be in roman.  */
01626   in_fixed_width_font = 0;
01627   
01628   /* The preceding newline already inserted the `current_indent'.
01629      Remove one level's worth.  */
01630   kill_self_indent (default_indentation_increment);
01631 
01632   if (html)
01633     add_word ("<br>");
01634   else if (docbook)
01635     xml_insert_element (LINEANNOTATION, START);
01636   else if (xml)
01637     xml_insert_element (EXDENT, START);
01638 
01639   /* Can't close_single_paragraph, then we lose preceding blank lines.  */
01640   flush_output ();
01641   execute_string ("%s", line);
01642   free (line);
01643 
01644   if (html)
01645     add_word ("<br>");
01646   else if (xml)
01647     {
01648       xml_insert_element (docbook ? LINEANNOTATION : EXDENT, END);
01649       insert ('\n');
01650     }
01651 
01652   close_single_paragraph ();
01653 
01654   current_indent = save_indent;
01655   in_fixed_width_font = save_in_fixed_width_font;
01656   if (!xml)
01657     start_paragraph ();
01658 }
01659 
01660 /* 
01661   Read include-filename, process the include-file:
01662     verbatim_include == 0: process through reader_loop
01663     verbatim_include != 0: process through handle_verbatim_environment
01664  */
01665 static void
01666 handle_include (int verbatim_include)
01667 {
01668   char *arg, *filename;
01669 
01670   if (macro_expansion_output_stream && !executing_string)
01671     me_append_before_this_command ();
01672 
01673   if (!insertion_stack)
01674     close_paragraph ();  /* No blank lines etc. if not at outer level.  */
01675     
01676   get_rest_of_line (0, &arg);
01677   /* We really only want to expand @value, but it's easier to just do
01678      everything.  TeX will only work with @value.  */
01679   filename = text_expansion (arg);
01680   free (arg);
01681 
01682   if (macro_expansion_output_stream && !executing_string)
01683     remember_itext (input_text, input_text_offset);
01684 
01685   pushfile ();
01686 
01687   /* In verbose mode we print info about including another file. */
01688   if (verbose_mode)
01689     {
01690       int i = 0;
01691       FSTACK *stack = filestack;
01692 
01693       for (i = 0, stack = filestack; stack; stack = stack->next, i++);
01694 
01695       i *= 2;
01696 
01697       printf ("%*s", i, "");
01698       printf ("%c%s `%s'\n", COMMAND_PREFIX, command, filename);
01699       fflush (stdout);
01700     }
01701 
01702   if (!find_and_load (filename, 1))
01703     {
01704       popfile ();
01705       line_number--;
01706 
01707       /* /wh/bar:5: @include/@verbatiminclude `foo': No such file or dir */
01708       line_error ("%c%s `%s': %s", COMMAND_PREFIX, command, filename,
01709                   strerror (errno));
01710 
01711       free (filename);
01712       return;
01713     }
01714   else
01715     {
01716       if (macro_expansion_output_stream && !executing_string)
01717        remember_itext (input_text, input_text_offset);
01718 
01719       if (!verbatim_include)
01720        reader_loop ();
01721       else
01722        handle_verbatim_environment (0);
01723     }
01724   free (filename);
01725   popfile ();
01726 }
01727 
01728 
01729 /* Include file as if put in @verbatim environment */
01730 void
01731 cm_verbatiminclude (void)
01732 {
01733   handle_include (1); 
01734 }
01735 
01736 
01737 /* Remember this file, and move onto the next. */
01738 void
01739 cm_include (void)
01740 {
01741   handle_include (0); 
01742 }
01743 
01744 
01745 /* @bye: Signals end of processing.  Easy to make this happen. */
01746 
01747 void
01748 cm_bye (void)
01749 {
01750   discard_braces (); /* should not have any unclosed braces left */
01751   input_text_offset = input_text_length;
01752 }
01753 
01754 /* @paragraphindent */
01755 
01756 static void
01757 cm_paragraphindent (void)
01758 {
01759   char *arg;
01760 
01761   get_rest_of_line (1, &arg);
01762   if (set_paragraph_indent (arg) != 0)
01763     line_error (_("Bad argument to %c%s"), COMMAND_PREFIX, command);
01764 
01765   free (arg);
01766 }
01767 
01768 
01769 /* @exampleindent: change indentation of example-like environments.   */
01770 static int
01771 set_example_indentation_increment (char *string)
01772 {
01773   if (strcmp (string, "asis") == 0 || strcmp (string, _("asis")) == 0)
01774     ;
01775   else if (strcmp (string, "none") == 0 || strcmp (string, _("none")) == 0)
01776     example_indentation_increment = 0;
01777   else if (sscanf (string, "%d", &example_indentation_increment) != 1)
01778     return -1;
01779   return 0;
01780 }
01781 
01782 static void
01783 cm_exampleindent (void)
01784 {
01785   char *arg;
01786   
01787   get_rest_of_line (1, &arg);
01788   if (set_example_indentation_increment (arg) != 0)
01789     line_error (_("Bad argument to @%s"), command);
01790 
01791   if (input_text[input_text_offset] == '\n')
01792     close_single_paragraph ();
01793 
01794   free (arg);
01795 }
01796 
01797 
01798 /* @firstparagraphindent: suppress indentation in first paragraphs after
01799    headings. */
01800 static int
01801 set_firstparagraphindent (char *string)
01802 {
01803   if (STREQ (string, "insert") || STREQ (string, _("insert")))
01804     do_first_par_indent = 1;
01805   else if (STREQ (string, "none") || STREQ (string, _("none")))
01806     do_first_par_indent = 0;
01807   else
01808     return -1;
01809   return 0;
01810 }
01811 
01812 static void
01813 cm_firstparagraphindent (void)
01814 {
01815   char *arg;
01816 
01817   get_rest_of_line (1, &arg);
01818   if (set_firstparagraphindent (arg) != 0)
01819     line_error (_("Bad argument to %c%s"), COMMAND_PREFIX, command);
01820 
01821   free (arg);
01822 }
01823 
01824 /* For DocBook and XML, produce &period; for `.@:'. This gives the processing
01825    software a fighting chance to treat it specially by not adding extra space.
01826   
01827    Do this also for ?, !, and :.  */
01828 void
01829 cm_colon (void)
01830 {
01831   if (xml)
01832     {
01833       if (strchr (".?!:", input_text[input_text_offset-3]) != NULL)
01834         {
01835           /* Erase literal character that's there, except `>', which is
01836              part of the XML tag.  */
01837           if (output_paragraph[output_paragraph_offset-1] != '>')
01838             output_paragraph_offset--;
01839 
01840           switch (input_text[input_text_offset-3])
01841             {
01842             case '.':
01843               xml_insert_entity ("period");
01844               break;
01845             case '?':
01846               xml_insert_entity ("quest");
01847               break;
01848             case '!':
01849               xml_insert_entity ("excl");
01850               break;
01851             case ':':
01852               xml_insert_entity ("colon");
01853               break;
01854             }
01855         }
01856     }
01857 }
01858 
01859 /* Ending sentences explicitly.  Currently, only outputs entities for XML
01860    output, for other formats it calls insert_self.  */
01861 void
01862 cm_punct (int arg)
01863 {
01864   if (xml && !docbook)
01865     {
01866       switch (input_text[input_text_offset-1])
01867         {
01868         case '.':
01869           xml_insert_entity ("eosperiod");
01870           break;
01871         case '?':
01872           xml_insert_entity ("eosquest");
01873           break;
01874         case '!':
01875           xml_insert_entity ("eosexcl");
01876           break;
01877         }
01878     }
01879   else
01880     {
01881       insert_self (arg);
01882     }
01883 }