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