Back to index

tetex-bin  3.0
xml.c
Go to the documentation of this file.
00001 /* xml.c -- xml output.
00002    $Id: xml.c,v 1.52 2004/12/19 17:02:23 karl Exp $
00003 
00004    Copyright (C) 2001, 2002, 2003, 2004 Free Software Foundation, Inc.
00005 
00006    This program is free software; you can redistribute it and/or modify
00007    it under the terms of the GNU General Public License as published by
00008    the Free Software Foundation; either version 2, or (at your option)
00009    any later version.
00010 
00011    This program is distributed in the hope that it will be useful,
00012    but WITHOUT ANY WARRANTY; without even the implied warranty of
00013    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00014    GNU General Public License for more details.
00015 
00016    You should have received a copy of the GNU General Public License
00017    along with this program; if not, write to the Free Software
00018    Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
00019 
00020    Originally written by Philippe Martin <feloy@free.fr>.  */
00021 
00022 #include "system.h"
00023 #include "makeinfo.h"
00024 #include "insertion.h"
00025 #include "files.h"
00026 #include "float.h"
00027 #include "macro.h"
00028 #include "cmds.h"
00029 #include "lang.h"
00030 
00031 #include "xml.h"
00032 
00033 /* Options */
00034 int xml_index_divisions = 1;
00035 
00036 typedef struct _element
00037 {
00038   char name[32];
00039   int contains_para;
00040   int contained_in_para;
00041   int keep_space;
00042 } element;
00043 
00044 element texinfoml_element_list [] = {
00045   { "texinfo",             1, 0, 0 },
00046   { "setfilename",         0, 0, 0 },
00047   { "titlefont",           0, 0, 0 },
00048   { "settitle",            0, 0, 0 },
00049   { "documentdescription", 1, 0, 0 },
00050 
00051   { "node",                1, 0, 0 },
00052   { "nodenext",            0, 0, 0 },
00053   { "nodeprev",            0, 0, 0 },
00054   { "nodeup",              0, 0, 0 },
00055 
00056   { "chapter",             1, 0, 0 },
00057   { "section",             1, 0, 0 },
00058   { "subsection",          1, 0, 0 },
00059   { "subsubsection",       1, 0, 0 },
00060 
00061   { "top",                 1, 0, 0 },
00062   { "unnumbered",          1, 0, 0 },
00063   { "unnumberedsec",       1, 0, 0 },
00064   { "unnumberedsubsec",    1, 0, 0 },
00065   { "unnumberedsubsubsec", 1, 0, 0 },
00066 
00067   { "appendix",            1, 0, 0 },
00068   { "appendixsec",         1, 0, 0 },
00069   { "appendixsubsec",      1, 0, 0 },
00070   { "appendixsubsubsec",   1, 0, 0 },
00071 
00072   { "majorheading",        0, 0, 0 },
00073   { "chapheading",         0, 0, 0 },
00074   { "heading",             0, 0, 0 },
00075   { "subheading",          0, 0, 0 },
00076   { "subsubheading",       0, 0, 0 },
00077 
00078   { "titlepage",           1, 0, 0 },
00079   { "author",              0, 0, 0 },
00080   { "booktitle",           0, 0, 0 },
00081   { "booksubtitle",        0, 0, 0 },
00082 
00083   { "menu",                1, 0, 0 },
00084   { "detailmenu",          1, 0, 0 },
00085   { "menuentry",           0, 0, 0 },
00086   { "menutitle",           0, 0, 0 },
00087   { "menucomment",         0, 0, 0 },
00088   { "menunode",            0, 0, 0 },
00089   { "nodename",            0, 0, 0 },
00090 
00091   { "acronym",             0, 1, 0 },
00092   { "acronymword",         0, 1, 0 },
00093   { "acronymdesc",         0, 1, 0 },
00094 
00095   { "abbrev",              0, 1, 0 },
00096   { "abbrevword",          0, 1, 0 },
00097   { "abbrevdesc",          0, 1, 0 },
00098 
00099   { "tt",                  0, 1, 0 },
00100   { "code",                0, 1, 0 },
00101   { "command",             0, 1, 0 },
00102   { "env",                 0, 1, 0 },
00103   { "file",                0, 1, 0 },
00104   { "option",              0, 1, 0 },
00105   { "samp",                0, 1, 0 },
00106   { "kbd",                 0, 1, 0 },
00107   { "url",                 0, 1, 0 },
00108   { "key",                 0, 1, 0 },
00109   { "var",                 0, 1, 0 },
00110   { "sc",                  0, 1, 0 },
00111   { "dfn",                 0, 1, 0 },
00112   { "emph",                0, 1, 0 },
00113   { "strong",              0, 1, 0 },
00114   { "cite",                0, 1, 0 },
00115   { "notfixedwidth",       0, 1, 0 },
00116   { "i",                   0, 1, 0 },
00117   { "b",                   0, 1, 0 },
00118   { "r",                   0, 1, 0 },
00119   { "slanted",             0, 1, 0 },
00120   { "sansserif",           0, 1, 0 },
00121 
00122   { "exdent",              0, 0, 0 },
00123 
00124   { "title",               0, 0, 0 },
00125   { "ifinfo",              1, 0, 0 },
00126   { "sp",                  0, 0, 0 },
00127   { "center",              1, 0, 0 },
00128   { "dircategory",         0, 0, 0 },
00129   { "quotation",           1, 0, 0 },
00130   { "example",             0, 0, 1 },
00131   { "smallexample",        0, 0, 1 },
00132   { "lisp",                0, 0, 1 },
00133   { "smalllisp",           0, 0, 1 },
00134   { "cartouche",           1, 0, 0 },
00135   { "copying",             1, 0, 0 },
00136   { "format",              0, 0, 1 },
00137   { "smallformat",         0, 0, 1 },
00138   { "display",             0, 0, 1 },
00139   { "smalldisplay",        0, 0, 1 },
00140   { "verbatim",            0, 0, 1 },
00141   { "footnote",            0, 1, 0 },
00142   { "",                    0, 1, 0 }, /* LINEANNOTATION (docbook) */
00143 
00144   { "",                    1, 0, 0 }, /* TIP (docbook)       */
00145   { "",                    1, 0, 0 }, /* NOTE (docbook)      */
00146   { "",                    1, 0, 0 }, /* IMPORTANT (docbook) */
00147   { "",                    1, 0, 0 }, /* WARNING (docbook)   */
00148   { "",                    1, 0, 0 }, /* CAUTION (docbook)   */
00149 
00150   { "itemize",             0, 0, 0 },
00151   { "itemfunction",        0, 0, 0 },
00152   { "item",                1, 0, 0 },
00153   { "enumerate",           0, 0, 0 },
00154   { "table",               0, 0, 0 },
00155   { "tableitem",           0, 0, 0 },
00156   { "tableterm",           0, 0, 0 },
00157 
00158   { "indexterm",           0, 1, 0 },
00159 
00160   { "math",                0, 1, 0 },
00161 
00162   { "dmn",                 0, 1, 0 },
00163 
00164   { "xref",                0, 1, 0 },
00165   { "xrefnodename",        0, 1, 0 },
00166   { "xrefinfoname",        0, 1, 0 },
00167   { "xrefprinteddesc",     0, 1, 0 },
00168   { "xrefinfofile",        0, 1, 0 },
00169   { "xrefprintedname",     0, 1, 0 },
00170 
00171   { "inforef",             0, 1, 0 },
00172   { "inforefnodename",     0, 1, 0 },
00173   { "inforefrefname",      0, 1, 0 },
00174   { "inforefinfoname",     0, 1, 0 },
00175 
00176   { "uref",                0, 1, 0 },
00177   { "urefurl",             0, 1, 0 },
00178   { "urefdesc",            0, 1, 0 },
00179   { "urefreplacement",     0, 1, 0 },
00180 
00181   { "email",               0, 1, 0 },
00182   { "emailaddress",        0, 1, 0 },
00183   { "emailname",           0, 1, 0 },
00184 
00185   { "group",               0, 0, 0 },
00186   { "float",               1, 0, 0 },
00187   { "floattype",           0, 0, 0 },
00188   { "floatpos",            0, 0, 0 },
00189   { "caption",             0, 0, 0 },
00190   { "shortcaption",        0, 0, 0 },
00191 
00192   { "",                    0, 0, 0 }, /* TABLE (docbook) */
00193   { "",                    0, 0, 0 }, /* FIGURE (docbook) */
00194   { "",                    0, 0, 0 }, /* EXAMPLE (docbook) */
00195   { "",                    1, 0, 0 }, /* SIDEBAR (docbook) */
00196 
00197   { "printindex",          0, 0, 0 },
00198   { "listoffloats",        0, 0, 0 },
00199   { "anchor",              0, 1, 0 },
00200 
00201   { "image",               0, 0, 0 },
00202   { "inlineimage",         0, 1, 0 },
00203   { "alttext",             0, 1, 0 },
00204 
00205   { "",                    0, 1, 0 }, /* PRIMARY (docbook) */
00206   { "",                    0, 1, 0 }, /* SECONDARY (docbook) */
00207   { "",                    0, 0, 0 }, /* INFORMALFIGURE (docbook) */
00208   { "",                    0, 0, 0 }, /* MEDIAOBJECT (docbook) */
00209   { "",                    0, 0, 0 }, /* IMAGEOBJECT (docbook) */
00210   { "",                    0, 0, 0 }, /* IMAGEDATA (docbook) */
00211   { "",                    0, 0, 0 }, /* TEXTOBJECT (docbook) */
00212   { "",                    0, 0, 0 }, /* INDEXENTRY (docbook) */
00213   { "",                    0, 0, 0 }, /* PRIMARYIE (docbook) */
00214   { "",                    0, 0, 0 }, /* SECONDARYIE (docbook) */
00215   { "",                    0, 0, 0 }, /* INDEXDIV (docbook) */
00216   { "multitable",          0, 0, 0 },
00217   { "",                    0, 0, 0 }, /* TGROUP (docbook) */
00218   { "columnfraction",      0, 0, 0 },
00219   { "thead",               0, 0, 0 },
00220   { "tbody",               0, 0, 0 },
00221   { "entry",               0, 0, 0 },
00222   { "row",                 0, 0, 0 },
00223   { "",                    0, 0, 0 }, /* BOOKINFO (docbook) */
00224   { "",                    0, 0, 0 }, /* ABSTRACT (docbook) */
00225   { "",                    0, 0, 0 }, /* REPLACEABLE (docbook) */
00226   { "",                    0, 0, 0 }, /* ENVAR (docbook) */
00227   { "",                    0, 0, 0 }, /* COMMENT (docbook) */
00228   { "",                    0, 0, 0 }, /* FUNCTION (docbook) */
00229   { "",                    0, 0, 0 }, /* LEGALNOTICE (docbook) */
00230 
00231   { "contents",            0, 0, 0 },
00232   { "shortcontents",       0, 0, 0 },
00233   { "documentlanguage",    0, 0, 0 },
00234 
00235   { "setvalue",            0, 0, 0 },
00236   { "clearvalue",          0, 0, 0 },
00237 
00238   { "definition",          0, 0, 0 },
00239   { "definitionterm",      0, 0, 0 },
00240   { "definitionitem",      1, 0, 0 },
00241   { "defcategory",         0, 0, 0 },
00242   { "deffunction",         0, 0, 0 },
00243   { "defvariable",         0, 0, 0 },
00244   { "defparam",            0, 0, 0 },
00245   { "defdelimiter",        0, 0, 0 },
00246   { "deftype",             0, 0, 0 },
00247   { "defparamtype",        0, 0, 0 },
00248   { "defdatatype",         0, 0, 0 },
00249   { "defclass",            0, 0, 0 },
00250   { "defclassvar",         0, 0, 0 },
00251   { "defoperation",        0, 0, 0 },
00252 
00253   { "para",                0, 0, 0 } /* Must be last */
00254   /* name / contains para / contained in para / preserve space */
00255 };
00256 
00257 element docbook_element_list [] = {
00258   { "book",                0, 0, 0 }, /* TEXINFO */
00259   { "",                    0, 0, 0 }, /* SETFILENAME */
00260   { "",                    0, 0, 0 }, /* TITLEINFO */
00261   { "title",               0, 0, 0 }, /* SETTITLE */
00262   { "",                    1, 0, 0 }, /* DOCUMENTDESCRIPTION (?) */
00263 
00264   { "",                    1, 0, 0 }, /* NODE */
00265   { "",                    0, 0, 0 }, /* NODENEXT */
00266   { "",                    0, 0, 0 }, /* NODEPREV */
00267   { "",                    0, 0, 0 }, /* NODEUP */
00268 
00269   { "chapter",             1, 0, 0 },
00270   { "sect1",               1, 0, 0 }, /* SECTION */
00271   { "sect2",               1, 0, 0 }, /* SUBSECTION */
00272   { "sect3",               1, 0, 0 }, /* SUBSUBSECTION */
00273 
00274   { "chapter",             1, 0, 0 }, /* TOP */
00275   { "chapter",             1, 0, 0 }, /* UNNUMBERED */
00276   { "sect1",               1, 0, 0 }, /* UNNUMBEREDSEC */
00277   { "sect2",               1, 0, 0 }, /* UNNUMBEREDSUBSEC */
00278   { "sect3",               1, 0, 0 }, /* UNNUMBEREDSUBSUBSEC */
00279 
00280   { "appendix",            1, 0, 0 },
00281   { "sect1",               1, 0, 0 }, /* APPENDIXSEC */
00282   { "sect2",               1, 0, 0 }, /* APPENDIXSUBSEC */
00283   { "sect3",               1, 0, 0 }, /* APPENDIXSUBSUBSEC */
00284 
00285   { "bridgehead",          0, 0, 0 }, /* MAJORHEADING */
00286   { "bridgehead",          0, 0, 0 }, /* CHAPHEADING */
00287   { "bridgehead",          0, 0, 0 }, /* HEADING */
00288   { "bridgehead",          0, 0, 0 }, /* SUBHEADING */
00289   { "bridgehead",          0, 0, 0 }, /* SUBSUBHEADING */
00290 
00291   { "",                    0, 0, 0 }, /* TITLEPAGE */
00292   { "",                    0, 0, 0 }, /* AUTHOR */
00293   { "",                    0, 0, 0 }, /* BOOKTITLE */
00294   { "",                    0, 0, 0 }, /* BOOKSUBTITLE */
00295 
00296   { "",                    1, 0, 0 }, /* MENU */
00297   { "",                    1, 0, 0 }, /* DETAILMENU */
00298   { "",                    1, 0, 0 }, /* MENUENTRY */
00299   { "",                    0, 0, 0 }, /* MENUTITLE */
00300   { "",                    1, 0, 0 }, /* MENUCOMMENT */
00301   { "",                    0, 0, 0 }, /* MENUNODE */
00302   { "anchor",              0, 0, 0 }, /* NODENAME */
00303 
00304   { "acronym",             0, 1, 0 },
00305   { "",                    0, 1, 0 }, /* ACRONYMWORD */
00306   { "",                    0, 1, 0 }, /* ACRONYMDESC */
00307 
00308   { "abbrev",              0, 1, 0 },
00309   { "",                    0, 1, 0 }, /* ABBREVWORD */
00310   { "",                    0, 1, 0 }, /* ABBREVDESC */
00311 
00312   { "literal",             0, 1, 0 }, /* TT */
00313   { "literal",             0, 1, 0 }, /* CODE */
00314   { "command",             0, 1, 0 }, /* COMMAND */
00315   { "envar",               0, 1, 0 }, /* ENV */
00316   { "filename",            0, 1, 0 }, /* FILE */
00317   { "option",              0, 1, 0 }, /* OPTION */
00318   { "literal",             0, 1, 0 }, /* SAMP */
00319   { "userinput",           0, 1, 0 }, /* KBD */
00320   { "wordasword",          0, 1, 0 }, /* URL */
00321   { "keycap",              0, 1, 0 }, /* KEY */
00322   { "replaceable",         0, 1, 0 }, /* VAR */
00323   { "",                    0, 1, 0 }, /* SC */
00324   { "firstterm",           0, 1, 0 }, /* DFN */
00325   { "emphasis",            0, 1, 0 }, /* EMPH */
00326   { "emphasis",            0, 1, 0 }, /* STRONG */
00327   { "citetitle",           0, 1, 0 }, /* CITE */
00328   { "",                    0, 1, 0 }, /* NOTFIXEDWIDTH */
00329   { "wordasword",          0, 1, 0 }, /* I */
00330   { "emphasis",            0, 1, 0 }, /* B */
00331   { "",                    0, 1, 0 }, /* R */
00332 
00333   { "",                    0, 0, 0 }, /* EXDENT */
00334 
00335   { "title",               0, 0, 0 },
00336   { "",                    1, 0, 0 }, /* IFINFO */
00337   { "",                    0, 0, 0 }, /* SP */
00338   { "",                    1, 0, 0 }, /* CENTER */
00339   { "",                    0, 0, 0 }, /* DIRCATEGORY */
00340   { "blockquote",          1, 0, 0 }, /* QUOTATION */
00341   { "screen",              0, 0, 1 }, /* EXAMPLE */
00342   { "screen",              0, 0, 1 }, /* SMALLEXAMPLE */
00343   { "programlisting",      0, 0, 1 }, /* LISP */
00344   { "programlisting",      0, 0, 1 }, /* SMALLLISP */
00345   { "",                    1, 0, 0 }, /* CARTOUCHE */
00346   { "",                    1, 0, 0 }, /* COPYING */
00347   { "screen",              0, 1, 1 }, /* FORMAT */
00348   { "screen",              0, 1, 1 }, /* SMALLFORMAT */
00349   { "literallayout",       0, 1, 1 }, /* DISPLAY */
00350   { "literallayout",       0, 1, 1 }, /* SMALLDISPLAY */
00351   { "screen",              0, 0, 1 }, /* VERBATIM */
00352   { "footnote",            0, 1, 0 },
00353   { "lineannotation",      0, 1, 0 },
00354 
00355   { "tip",                 1, 0, 0 },
00356   { "note",                1, 0, 0 },
00357   { "important",           1, 0, 0 },
00358   { "warning",             1, 0, 0 },
00359   { "caution",             1, 0, 0 },
00360 
00361   { "itemizedlist",        0, 0, 0 }, /* ITEMIZE */
00362   { "",                    0, 0, 0 }, /* ITEMFUNCTION */
00363   { "listitem",            1, 0, 0 }, /* ITEM */
00364   { "orderedlist",         0, 0, 0 }, /* ENUMERATE */
00365   { "variablelist",        0, 0, 0 }, /* TABLE */
00366   { "varlistentry",        0, 0, 0 }, /* TABLEITEM */
00367   { "term",                0, 0, 0 }, /* TABLETERM */
00368 
00369   { "indexterm",           0, 1, 0 }, /* INDEXTERM */
00370 
00371   { "",                    0, 1, 0 }, /* MATH */
00372 
00373   { "",                    0, 1, 0 }, /* DIMENSION */
00374 
00375   { "xref",                0, 1, 0 }, /* XREF */
00376   { "link",                0, 1, 0 }, /* XREFNODENAME */
00377   { "",                    0, 1, 0 }, /* XREFINFONAME */
00378   { "",                    0, 1, 0 }, /* XREFPRINTEDDESC */
00379   { "",                    0, 1, 0 }, /* XREFINFOFILE */
00380   { "",                    0, 1, 0 }, /* XREFPRINTEDNAME */
00381 
00382   { "",                    0, 1, 0 }, /* INFOREF */
00383   { "",                    0, 1, 0 }, /* INFOREFNODENAME */
00384   { "",                    0, 1, 0 }, /* INFOREFREFNAME */
00385   { "",                    0, 1, 0 }, /* INFOREFINFONAME */
00386 
00387   { "ulink",               0, 1, 0 }, /* UREF */
00388   { "",                    0, 1, 0 }, /* UREFURL */
00389   { "",                    0, 1, 0 }, /* UREFDESC */
00390   { "",                    0, 1, 0 }, /* UREFREPLACEMENT */
00391 
00392   { "ulink",               0, 1, 0 }, /* EMAIL */
00393   { "",                    0, 1, 0 }, /* EMAILADDRESS */
00394   { "",                    0, 1, 0 }, /* EMAILNAME */
00395 
00396   { "",                    0, 0, 0 }, /* GROUP */
00397   { "",                    1, 0, 0 }, /* FLOAT */
00398   { "",                    0, 0, 0 }, /* FLOATTYPE */
00399   { "",                    0, 0, 0 }, /* FLOATPOS */
00400   { "",                    0, 0, 0 }, /* CAPTION */
00401   { "",                    0, 0, 0 }, /* SHORTCAPTION */
00402 
00403   { "table",               0, 1, 0 },
00404   { "figure",              0, 1, 0 },
00405   { "example",             1, 1, 0 },
00406   { "sidebar",             1, 0, 0 },
00407 
00408   { "index",               0, 1, 0 }, /* PRINTINDEX */
00409   { "",                    0, 1, 0 }, /* LISTOFFLOATS */
00410   { "",                    0, 1, 0 }, /* ANCHOR */
00411 
00412   { "",                    0, 0, 0 }, /* IMAGE */
00413   { "inlinemediaobject",   0, 1, 0 }, /* INLINEIMAGE */
00414   { "",                    0, 0, 0 }, /* IMAGEALTTEXT */
00415 
00416   { "primary",             0, 1, 0 }, /* PRIMARY */
00417   { "secondary",           0, 1, 0 },
00418   { "informalfigure",      0, 0, 0 },
00419   { "mediaobject",         0, 0, 0 },
00420   { "imageobject",         0, 1, 0 },
00421   { "imagedata",           0, 1, 0 },
00422   { "textobject",          0, 1, 0 },
00423   { "indexentry",          0, 0, 0 },
00424   { "primaryie",           0, 0, 0 },
00425   { "secondaryie",         0, 0, 0 },
00426   { "indexdiv",            0, 0, 0 },
00427   { "informaltable",       0, 0, 0 },
00428   { "tgroup",              0, 0, 0 },
00429   { "colspec",             0, 0, 0 },
00430   { "thead",               0, 0, 0 },
00431   { "tbody",               0, 0, 0 },
00432   { "entry",               0, 0, 0 },
00433   { "row",                 0, 0, 0 },
00434   { "bookinfo",            0, 0, 0 },
00435   { "abstract",            1, 0, 0 },
00436   { "replaceable",         0, 0, 0 },
00437   { "envar",               0, 1, 0 },
00438   { "comment",             0, 0, 0 },
00439   { "function",            0, 1, 0 },
00440   { "legalnotice",         1, 0, 0 },
00441 
00442   { "",                    0, 0, 0 }, /* CONTENTS (xml) */
00443   { "",                    0, 0, 0 }, /* SHORTCONTENTS (xml) */
00444   { "",                    0, 0, 0 }, /* DOCUMENT LANGUAGE (xml) */
00445 
00446   { "",                    0, 0, 0 }, /* SETVALUE (xml) */
00447   { "",                    0, 0, 0 }, /* CLEARVALUE (xml) */
00448 
00449   { "blockquote",          1, 0, 0 }, /* DEFINITION */
00450   { "screen",              0, 0, 1 }, /* DEFINITIONTERM */
00451   { "",                    0, 0, 0 }, /* DEFINITIONITEM (xml) */
00452   { "",                    0, 0, 0 }, /* DEFCATEGORY (xml) */
00453   { "function",            0, 0, 0 }, /* DEFFUNCTION */
00454   { "varname",             0, 0, 0 }, /* DEFVARIABLE */
00455   { "varname",             0, 0, 0 }, /* DEFPARAM */
00456   { "",                    0, 0, 0 }, /* DEFDELIMITER (xml) */
00457   { "returnvalue",         0, 0, 0 }, /* DEFTYPE */
00458   { "type",                0, 0, 0 }, /* DEFPARAMTYPE */
00459   { "structname",          0, 0, 0 }, /* DEFDATATYPE */
00460   { "classname",           0, 0, 0 }, /* DEFCLASS */
00461   { "property",            0, 0, 0 }, /* DEFCLASSVAR */
00462   { "methodname",          0, 0, 0 }, /* DEFOPERATION */
00463 
00464   { "para",                0, 0, 0 } /* Must be last */
00465   /* name / contains para / contained in para / preserve space */
00466 };
00467 
00468 element *xml_element_list = NULL;
00469 
00470 
00471 typedef struct _replace_element
00472 {
00473   int element_to_replace;
00474   int element_containing;
00475   int element_replacing;
00476 } replace_element;
00477 
00478 /* Elements to replace - Docbook only
00479    -------------------
00480    if `element_to_replace' have to be inserted
00481    as a child of `element_containing,'
00482    use `element_replacing' instead.
00483 
00484    A value of `-1' for element_replacing means `do not use any element.'
00485 */
00486 
00487 replace_element replace_elements [] = {
00488   { I, TABLETERM, EMPH },
00489   { B, TABLETERM, EMPH },
00490   { TT, CODE, -1 },
00491   { EXAMPLE, DISPLAY, -1 },
00492   { CODE, DFN, -1 },
00493   { CODE, VAR, -1 },
00494   { EMPH, CODE, REPLACEABLE },
00495   { VAR, VAR, -1},
00496   { VAR, B, EMPH},
00497   { B, CODE, ENVAR},
00498   { CODE, I, EMPH},
00499   { SAMP, VAR, -1 },
00500   { FORMAT, BOOKINFO, ABSTRACT },
00501   { QUOTATION, ABSTRACT, -1},
00502   { LINEANNOTATION, LINEANNOTATION, -1 },
00503   { LEGALNOTICE, ABSTRACT, -1 },
00504   { QUOTATION, QUOTATION, -1 },
00505   /* Formal versions of table and image elements.  */
00506   { MULTITABLE, FLOAT, FLOATTABLE },
00507   { INFORMALFIGURE, FLOAT, FLOATFIGURE },
00508   { CARTOUCHE, FLOAT, FLOATCARTOUCHE },
00509   /* Unnecessary markup in @defun blocks.  */
00510   { VAR, DEFPARAM, -1 },
00511   { CODE, DEFTYPE, -1 },
00512   /* Add your elements to replace here */
00513   {-1, 0, 0}
00514 };
00515 
00516 int xml_in_menu_entry = 0;
00517 int xml_in_menu_entry_comment = 0;
00518 int xml_node_open = 0;
00519 int xml_node_level = -1;
00520 int xml_in_para = 0;
00521 int xml_just_after_element = 0;
00522 int xml_keep_space = 0;
00523 
00524 int xml_no_indent = 0;
00525 
00526 int xml_no_para = 0;
00527 char *xml_node_id = NULL;
00528 int xml_sort_index = 0;
00529 
00530 int xml_in_xref_token = 0;
00531 int xml_in_bookinfo = 0;
00532 int xml_in_book_title = 0;
00533 int xml_in_abstract = 0;
00534 
00535 /* Non-zero if we are handling an element that can appear between
00536    @item and @itemx, @deffn and @deffnx.  */
00537 int xml_dont_touch_items_defs = 0;
00538 
00539 /* We need to keep footnote state, because elements inside footnote may try
00540    to close the previous parent para.  */
00541 static int xml_in_footnote = 0;
00542 
00543 static int xml_after_table_term = 0;
00544 static int book_started = 0;
00545 static int first_section_opened = 0;
00546 
00547 static int xml_in_tableitem[256];
00548 static int xml_in_item[256];
00549 static int xml_table_level = 0;
00550 
00551 static int xml_in_def_item[256];
00552 static int xml_definition_level = 0;
00553 int xml_after_def_term = 0;
00554 
00555 static int in_table_title = 0;
00556 
00557 static int in_indexentry = 0;
00558 static int in_secondary = 0;
00559 static int in_indexterm = 0;
00560 
00561 char *
00562 xml_id (char *id)
00563 {
00564   char *tem = xmalloc (strlen (id) + 1);
00565   char *p = tem;
00566   strcpy (tem, id);
00567   while (*p)
00568     { /* Check if a character is allowed in ID attributes.  This list differs
00569          slightly from XML specs that it doesn't contain underscores.
00570          See http://xml.coverpages.org/sgmlsyn/sgmlsyn.htm, ``9.3 Name''  */
00571       if (!strchr ("abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789-.", *p))
00572         *p = '-';
00573       p++;
00574     }
00575   p = tem;
00576   /* First character can only be a letter.  */
00577   if (!strchr ("abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ", *p))
00578     *p = 'i';
00579   return tem;
00580 }
00581 
00582 int
00583 xml_element (char *name)
00584 {
00585   int i;
00586   for (i=0; i<=PARA; i++)
00587     {
00588       if (strcasecmp (name, texinfoml_element_list[i].name) == 0)
00589         return i;
00590     }
00591   printf ("Error xml_element\n");
00592   return -1;
00593 }
00594 
00595 void
00596 xml_begin_document (char *output_filename)
00597 {
00598   if (book_started)
00599     return;
00600 
00601   book_started = 1;
00602 
00603   /* Make sure this is the very first string of the output document.  */
00604   output_paragraph_offset = 0;
00605 
00606   insert_string ("<?xml version=\"1.0\"");
00607 
00608   /* At this point, we register a delayed writing for document encoding,
00609      so in the end, proper encoding attribute will be inserted here.
00610      Since the user is unaware that we are implicitly executing this
00611      command, we should disable warnings temporarily, in order to avoid
00612      possible confusion.  (ie. if the output is not seekable,
00613      register_delayed_write issues a warning.)  */
00614   {
00615     extern int print_warnings;
00616     int save_print_warnings = print_warnings;
00617     print_warnings = 0;
00618     register_delayed_write ("@documentencoding");
00619     print_warnings = save_print_warnings;
00620   }
00621 
00622   insert_string ("?>\n");
00623 
00624   if (docbook)
00625     {
00626       insert_string ("<!DOCTYPE book PUBLIC \"-//OASIS//DTD DocBook XML V4.2//EN\" \"http://www.oasis-open.org/docbook/xml/4.2/docbookx.dtd\" [\n  <!ENTITY tex \"TeX\">\n  <!ENTITY latex \"LaTeX\">\n]>");
00627       xml_element_list = docbook_element_list;
00628     }
00629   else
00630     {
00631       insert_string ("<!DOCTYPE texinfo PUBLIC \"-//GNU//DTD TexinfoML V");
00632       insert_string (VERSION);
00633       insert_string ("//EN\" \"http://www.gnu.org/software/texinfo/dtd/");
00634       insert_string (VERSION);
00635       insert_string ("/texinfo.dtd\">");
00636       xml_element_list = texinfoml_element_list;
00637     }
00638   if (language_code != last_language_code)
00639     {
00640       if (docbook)
00641         xml_insert_element_with_attribute (TEXINFO, START, "lang=\"%s\"", language_table[language_code].abbrev);
00642       else
00643        xml_insert_element_with_attribute (TEXINFO, START, "xml:lang=\"%s\"", language_table[language_code].abbrev);
00644     }
00645   if (!docbook)
00646     {
00647       xml_insert_element (SETFILENAME, START);
00648       insert_string (output_filename);
00649       xml_insert_element (SETFILENAME, END);
00650     }
00651 }
00652 
00653 /*  */
00654 static int element_stack[256];
00655 static int element_stack_index = 0;
00656 
00657 static int
00658 xml_current_element (void)
00659 {
00660   return element_stack[element_stack_index-1];
00661 }
00662 
00663 static void
00664 xml_push_current_element (int elt)
00665 {
00666   element_stack[element_stack_index++] = elt;
00667   if (element_stack_index > 200)
00668     printf ("*** stack overflow (%d - %s) ***\n",
00669             element_stack_index,
00670             xml_element_list[elt].name);
00671 }
00672 
00673 static void
00674 xml_pop_current_element (void)
00675 {
00676   element_stack_index--;
00677   if (element_stack_index < 0)
00678     printf ("*** stack underflow (%d - %d) ***\n",
00679             element_stack_index,
00680             xml_current_element());
00681 }
00682 
00683 int
00684 xml_current_stack_index (void)
00685 {
00686   return element_stack_index;
00687 }
00688 
00689 void
00690 xml_end_current_element (void)
00691 {
00692   xml_insert_element (xml_current_element (), END);
00693 }
00694 
00695 static void
00696 xml_indent (void)
00697 {
00698   if (xml_indentation_increment > 0)
00699     {
00700       int i;
00701       if (output_paragraph[output_paragraph_offset-1] != '\n')
00702         insert ('\n');
00703       for (i = 0; i < element_stack_index * xml_indentation_increment; i++)
00704         insert (' ');
00705     }
00706 }
00707 
00708 void
00709 xml_start_para (void)
00710 {
00711   if (xml_in_para || xml_in_footnote
00712       || !xml_element_list[xml_current_element()].contains_para)
00713     return;
00714 
00715   while (output_paragraph[output_paragraph_offset-1] == '\n')
00716     output_paragraph_offset--;
00717   xml_indent ();
00718 
00719   insert_string ("<para");
00720   if (xml_no_indent)
00721     insert_string (" role=\"continues\"");
00722   insert_string (">");
00723   xml_no_indent = 0;
00724   xml_in_para = 1;
00725 }
00726 
00727 void
00728 xml_end_para (void)
00729 {
00730   if (!xml_in_para || xml_in_footnote)
00731     return;
00732 
00733   while (cr_or_whitespace(output_paragraph[output_paragraph_offset-1]))
00734     output_paragraph_offset--;
00735 
00736   insert_string ("</para>");
00737   if (xml_indentation_increment > 0)
00738     insert ('\n');
00739   xml_in_para = 0;
00740 }
00741 
00742 void
00743 xml_end_document (void)
00744 {
00745   if (xml_node_open)
00746     {
00747       if (xml_node_level != -1)
00748         {
00749           xml_close_sections (xml_node_level);
00750           xml_node_level = -1;
00751         }
00752       xml_insert_element (NODE, END);
00753     }
00754   else
00755     xml_close_sections (xml_node_level);
00756 
00757   xml_insert_element (TEXINFO, END);
00758   if (xml_indentation_increment == 0)
00759     insert ('\n');
00760   insert_string ("<!-- Keep this comment at the end of the file\n\
00761 Local variables:\n\
00762 mode: sgml\n\
00763 sgml-indent-step:1\n\
00764 sgml-indent-data:nil\n\
00765 End:\n\
00766 -->\n");
00767   if (element_stack_index != 0)
00768     error ("Element stack index : %d\n", element_stack_index);
00769 }
00770 
00771 /* MUST be 0 or 1, not true or false values */
00772 static int start_element_inserted = 1;
00773 
00774 /* NOTE: We use `elt' rather than `element' in the argument list of
00775    the next function, since otherwise the Solaris SUNWspro compiler
00776    barfs because `element' is a typedef declared near the beginning of
00777    this file.  */
00778 void
00779 #if defined (VA_FPRINTF) && __STDC__
00780 xml_insert_element_with_attribute (int elt, int arg, char *format, ...)
00781 #else
00782 xml_insert_element_with_attribute (elt, arg, format, va_alist)
00783      int elt;
00784      int arg;
00785      char *format;
00786      va_dcl
00787 #endif
00788 {
00789   /* Look at the replace_elements table to see if we have to change the element */
00790   if (xml_sort_index)
00791       return;
00792   if (docbook)
00793     {
00794       replace_element *element_list = replace_elements;
00795       while (element_list->element_to_replace >= 0)
00796         {
00797           if ( ( (arg == START) &&
00798                  (element_list->element_containing == xml_current_element ()) &&
00799                  (element_list->element_to_replace == elt) ) ||
00800                ( (arg == END) &&
00801                  (element_list->element_containing == element_stack[element_stack_index-1-start_element_inserted]) &&
00802                  (element_list->element_to_replace == elt) ) )
00803             {
00804               elt = element_list->element_replacing;
00805               break;
00806             }
00807           element_list ++;
00808         }
00809 
00810       /* Forget the element */
00811       if (elt < 0)
00812         {
00813           if (arg == START)
00814             start_element_inserted = 0;
00815           else
00816             /* Replace the default value, for the next time */
00817             start_element_inserted = 1;
00818           return;
00819         }
00820     }
00821 
00822   if (!book_started)
00823     return;
00824 
00825   if (!xml_dont_touch_items_defs && arg == START)
00826     {
00827       if (xml_after_table_term && elt != TABLETERM && xml_table_level
00828           && !xml_in_item[xml_table_level])
00829         {
00830           xml_after_table_term = 0;
00831           xml_insert_element (ITEM, START);
00832           xml_in_item[xml_table_level] = 1;
00833         }
00834       else if (xml_after_def_term && elt != DEFINITIONTERM)
00835         {
00836           xml_after_def_term = 0;
00837           xml_insert_element (DEFINITIONITEM, START);
00838           xml_in_def_item[xml_definition_level] = 1;
00839         }
00840     }
00841 
00842   if (docbook && !only_macro_expansion && (in_menu || in_detailmenu))
00843     return;
00844 
00845   if (executing_string && arg == END)
00846     switch (elt)
00847       {
00848       case TABLEITEM:
00849         xml_in_tableitem[xml_table_level] = 0;
00850         break;
00851       case ITEM:
00852         xml_in_item[xml_table_level] = 0;
00853         break;
00854       case DEFINITIONTERM:
00855         xml_in_def_item[xml_definition_level] = 0;
00856         break;
00857       }
00858 
00859   /* We are special-casing FIGURE element for docbook.  It does appear in
00860      the tag stack, but not in the output.  This is to make element replacement
00861      work beautifully.  */
00862   if (docbook && elt == FLOAT)
00863     {
00864       if (arg == START)
00865         xml_push_current_element (elt);
00866       else
00867         xml_pop_current_element ();
00868       return;
00869     }
00870 
00871   if (!xml_element_list[elt].name || !strlen (xml_element_list[elt].name))
00872     {
00873       /*printf ("Warning: Inserting empty element %d\n", elt);*/
00874       return;
00875     }
00876 
00877   if (arg == START && !xml_in_para && !xml_no_para
00878       && xml_element_list[elt].contained_in_para)
00879     xml_start_para ();
00880 
00881   if (arg == START && xml_in_para && !xml_element_list[elt].contained_in_para)
00882     xml_end_para ();
00883 
00884   if (arg == END && xml_in_para && !xml_element_list[elt].contained_in_para)
00885     xml_end_para ();
00886 
00887   if (docbook && xml_table_level && !in_table_title
00888       && !xml_in_tableitem[xml_table_level] && !xml_in_item[xml_table_level]
00889       && arg == START && elt != TABLEITEM && elt != TABLETERM
00890       && !in_indexterm && xml_current_element() == TABLE)
00891     {
00892       in_table_title = 1;
00893       xml_insert_element (TITLE, START);
00894     }
00895 
00896   if (arg == START && !xml_in_para && !xml_keep_space
00897       && !xml_element_list[elt].contained_in_para)
00898     xml_indent ();
00899 
00900   if (arg == START)
00901     xml_push_current_element (elt);
00902   else
00903     xml_pop_current_element ();
00904 
00905   /* Eat one newline before </example> and the like.  */
00906   if (!docbook && arg == END
00907       && (xml_element_list[elt].keep_space || elt == GROUP)
00908       && output_paragraph[output_paragraph_offset-1] == '\n')
00909     output_paragraph_offset--;
00910 
00911   /* And eat whitespace before </entry> in @multitables.  */
00912   if (arg == END && elt == ENTRY)
00913       while (cr_or_whitespace(output_paragraph[output_paragraph_offset-1]))
00914     output_paragraph_offset--;
00915 
00916   /* Indent elements that can contain <para>.  */
00917   if (arg == END && !xml_in_para && !xml_keep_space
00918       && xml_element_list[elt].contains_para)
00919     xml_indent ();
00920 
00921   /* Here are the elements we want indented.  These do not contain <para>
00922      directly.  */
00923   if (arg == END && (elt == MENUENTRY || elt == ITEMIZE || elt == ENUMERATE
00924         || elt == TABLEITEM || elt == TABLE
00925         || elt == MULTITABLE || elt == TGROUP || elt == THEAD || elt == TBODY
00926         || elt == ROW || elt == INFORMALFIGURE
00927         || (!docbook && (elt == DEFINITION || elt == DEFINITIONTERM))))
00928     xml_indent ();
00929 
00930   insert ('<');
00931   if (arg == END)
00932     insert ('/');
00933   insert_string (xml_element_list[elt].name);
00934 
00935   /*  printf ("%s ", xml_element_list[elt].name);*/
00936 
00937   if (format)
00938     {
00939       char temp_string[2000]; /* xx no fixed limits */
00940 #ifdef VA_SPRINTF
00941       va_list ap;
00942 #endif
00943 
00944       VA_START (ap, format);
00945 #ifdef VA_SPRINTF
00946       VA_SPRINTF (temp_string, format, ap);
00947 #else
00948       sprintf (temp_string, format, a1, a2, a3, a4, a5, a6, a7, a8);
00949 #endif
00950       insert (' ');
00951       insert_string (temp_string);
00952       va_end (ap);
00953     }
00954 
00955   if (arg == START && xml_node_id && elt != NODENAME)
00956     {
00957       insert_string (" id=\"");
00958       insert_string (xml_node_id);
00959       insert ('"');
00960       free (xml_node_id);
00961       xml_node_id = NULL;
00962     }
00963 
00964   if (xml_element_list[elt].keep_space)
00965     {
00966       if (arg == START)
00967        {
00968           if (!docbook)
00969             insert_string (" xml:space=\"preserve\"");
00970          xml_keep_space++;
00971        }
00972       else
00973        xml_keep_space--;
00974     }
00975 
00976   insert ('>');
00977 
00978   if (!xml_in_para && !xml_element_list[elt].contained_in_para
00979       && xml_element_list[elt].contains_para && xml_indentation_increment > 0)
00980     insert ('\n');
00981 
00982   xml_just_after_element = 1;
00983 }
00984 
00985 /* See the NOTE before xml_insert_element_with_attribute, for why we
00986    use `elt' rather than `element' here.  */
00987 void
00988 xml_insert_element (int elt, int arg)
00989 {
00990   xml_insert_element_with_attribute (elt, arg, NULL);
00991 }
00992 
00993 void
00994 xml_insert_entity (char *entity_name)
00995 {
00996   int saved_escape_html = escape_html;
00997 
00998   if (!book_started)
00999     return;
01000   if (docbook && !only_macro_expansion && (in_menu || in_detailmenu))
01001     return;
01002 
01003   if (!xml_in_para && !xml_no_para && !only_macro_expansion
01004       && xml_element_list[xml_current_element ()].contains_para
01005       && !in_fixed_width_font)
01006     xml_start_para ();
01007 
01008   escape_html = 0;
01009   add_char ('&');
01010   escape_html = saved_escape_html;
01011   insert_string (entity_name);
01012   add_char (';');
01013 }
01014 
01015 typedef struct _xml_section xml_section;
01016 struct _xml_section {
01017   int level;
01018   char *name;
01019   xml_section *prev;
01020 };
01021 
01022 xml_section *last_section = NULL;
01023 
01024 void
01025 xml_begin_node (void)
01026 {
01027   first_section_opened = 1;
01028   if (xml_in_abstract)
01029     {
01030       xml_insert_element (ABSTRACT, END);
01031       xml_in_abstract = 0;
01032     }
01033   if (xml_in_bookinfo)
01034     {
01035       xml_insert_element (BOOKINFO, END);
01036       xml_in_bookinfo = 0;
01037     }
01038   if (xml_node_open && ! docbook)
01039     {
01040       if (xml_node_level != -1)
01041         {
01042           xml_close_sections (xml_node_level);
01043           xml_node_level = -1;
01044         }
01045       xml_insert_element (NODE, END);
01046     }
01047   xml_insert_element (NODE, START);
01048   xml_node_open = 1;
01049 }
01050 
01051 void
01052 xml_close_sections (int level)
01053 {
01054   if (!first_section_opened)
01055     {
01056       if (xml_in_abstract)
01057        {
01058          xml_insert_element (ABSTRACT, END);
01059          xml_in_abstract = 0;
01060        }
01061       if (xml_in_bookinfo)
01062        {
01063          xml_insert_element (BOOKINFO, END);
01064          xml_in_bookinfo = 0;
01065        }
01066       first_section_opened = 1;
01067     }
01068 
01069   while (last_section && last_section->level >= level)
01070     {
01071       xml_section *temp = last_section;
01072       xml_insert_element (xml_element(last_section->name), END);
01073       temp = last_section;
01074       last_section = last_section->prev;
01075       free (temp->name);
01076       free (temp);
01077     }
01078 }
01079 
01080 void
01081 xml_open_section (int level, char *name)
01082 {
01083   xml_section *sect = (xml_section *) xmalloc (sizeof (xml_section));
01084 
01085   sect->level = level;
01086   sect->name = xmalloc (1 + strlen (name));
01087   strcpy (sect->name, name);
01088   sect->prev = last_section;
01089   last_section = sect;
01090 
01091   if (xml_node_open && xml_node_level == -1)
01092     xml_node_level = level;
01093 }
01094 
01095 void
01096 xml_start_menu_entry (char *tem)
01097 {
01098   char *string;
01099   discard_until ("* ");
01100 
01101   /* The line number was already incremented in reader_loop when we
01102      saw the newline, and discard_until has now incremented again.  */
01103   line_number--;
01104 
01105   if (xml_in_menu_entry)
01106     {
01107       if (xml_in_menu_entry_comment)
01108         {
01109           xml_insert_element (MENUCOMMENT, END);
01110           xml_in_menu_entry_comment=0;
01111         }
01112       xml_insert_element (MENUENTRY, END);
01113       xml_in_menu_entry=0;
01114     }
01115   xml_insert_element (MENUENTRY, START);
01116   xml_in_menu_entry=1;
01117 
01118   xml_insert_element (MENUNODE, START);
01119   string = expansion (tem, 0);
01120   add_word (string);
01121   xml_insert_element (MENUNODE, END);
01122   free (string);
01123 
01124   /* The menu item may use macros, so expand them now.  */
01125   xml_insert_element (MENUTITLE, START);
01126   only_macro_expansion++;
01127   get_until_in_line (1, ":", &string);
01128   only_macro_expansion--;
01129   execute_string ("%s", string); /* get escaping done */
01130   xml_insert_element (MENUTITLE, END);
01131   free (string);
01132 
01133   if (looking_at ("::"))
01134     discard_until (":");
01135   else
01136     { /* discard the node name */
01137       get_until_in_line (0, ".", &string);
01138       free (string);
01139     }
01140   input_text_offset++;  /* discard the second colon or the period */
01141   skip_whitespace_and_newlines();
01142   xml_insert_element (MENUCOMMENT, START);
01143   xml_in_menu_entry_comment ++;
01144 }
01145 
01146 void
01147 xml_end_menu (void)
01148 {
01149   if (xml_in_menu_entry)
01150     {
01151       if (xml_in_menu_entry_comment)
01152         {
01153           xml_insert_element (MENUCOMMENT, END);
01154           xml_in_menu_entry_comment --;
01155         }
01156       xml_insert_element (MENUENTRY, END);
01157       xml_in_menu_entry--;
01158     }
01159   xml_insert_element (MENU, END);
01160 }
01161 
01162 static int xml_last_character;
01163 
01164 void
01165 xml_add_char (int character)
01166 {
01167   if (!book_started)
01168       return;
01169   if (docbook && !only_macro_expansion && (in_menu || in_detailmenu))
01170     return;
01171 
01172   if (docbook && xml_table_level && !in_table_title
01173       && !xml_in_item[xml_table_level] && !xml_in_tableitem[xml_table_level]
01174       && !cr_or_whitespace (character) && !in_indexterm)
01175     {
01176       in_table_title = 1;
01177       xml_insert_element (TITLE, START);
01178     }
01179 
01180   if (!first_section_opened && !xml_in_abstract && !xml_in_book_title
01181       && !xml_no_para && character != '\r' && character != '\n'
01182       && character != ' ' && !is_in_insertion_of_type (copying))
01183     {
01184       if (!xml_in_bookinfo)
01185        {
01186          xml_insert_element (BOOKINFO, START);
01187          xml_in_bookinfo = 1;
01188        }
01189       xml_insert_element (ABSTRACT, START);
01190       xml_in_abstract = 1;
01191     }
01192 
01193   if (!xml_sort_index && !xml_in_xref_token && !xml_dont_touch_items_defs)
01194     {
01195       if (xml_after_table_term && xml_table_level
01196           && !xml_in_item[xml_table_level])
01197         {
01198           xml_after_table_term = 0;
01199           xml_insert_element (ITEM, START);
01200           xml_in_item[xml_table_level] = 1;
01201         }
01202       else if (xml_after_def_term)
01203         {
01204           xml_after_def_term = 0;
01205           xml_insert_element (DEFINITIONITEM, START);
01206           xml_in_def_item[xml_definition_level] = 1;
01207         }
01208     }
01209 
01210   if (xml_just_after_element && !xml_in_para && !inhibit_paragraph_indentation)
01211     {
01212       if (character == '\r' || character == '\n' || character == '\t' || character == ' ')
01213         return;
01214       xml_just_after_element = 0;
01215     }
01216 
01217   if (xml_element_list[xml_current_element()].contains_para
01218       && !xml_in_para && !only_macro_expansion && !xml_no_para
01219       && !cr_or_whitespace (character) && !in_fixed_width_font)
01220     xml_start_para ();
01221 
01222   if (xml_in_para && character == '\n' && xml_last_character == '\n'
01223       && !only_macro_expansion && !xml_no_para
01224       && xml_element_list[xml_current_element()].contains_para )
01225     {
01226       xml_end_para ();
01227       xml_just_after_element = 1;
01228       return;
01229     }
01230 
01231   if (xml_in_menu_entry_comment && character == '\n' && xml_last_character == '\n')
01232     {
01233       xml_insert_element (MENUCOMMENT, END);
01234       xml_in_menu_entry_comment = 0;
01235       xml_insert_element (MENUENTRY, END);
01236       xml_in_menu_entry = 0;
01237     }
01238 
01239   if (xml_in_menu_entry_comment && whitespace(character)
01240       && cr_or_whitespace(xml_last_character))
01241     return;
01242 
01243   if (character == '\n' && !xml_in_para && !inhibit_paragraph_indentation)
01244     return;
01245 
01246   xml_last_character = character;
01247 
01248   if (character == '&' && escape_html)
01249       insert_string ("&amp;");
01250   else if (character == '<' && escape_html)
01251       insert_string ("&lt;");
01252   else if (character == '\n' && !xml_keep_space)
01253     {
01254       if (!xml_in_para && xml_just_after_element && !multitable_active)
01255        return;
01256       else
01257        insert (docbook ? '\n' : ' ');
01258     }
01259   else
01260     insert (character);
01261 
01262   return;
01263 }
01264 
01265 void
01266 xml_insert_footnote (char *note)
01267 {
01268   if (!xml_in_para)
01269     xml_start_para ();
01270 
01271   xml_in_footnote = 1;
01272   xml_insert_element (FOOTNOTE, START);
01273   insert_string ("<para>");
01274   execute_string ("%s", note);
01275   insert_string ("</para>");
01276   xml_insert_element (FOOTNOTE, END);
01277   xml_in_footnote = 0;
01278 }
01279 
01280 /* We need to keep the quotation stack ourself, because insertion_stack
01281    loses item_function when we are closing the block, so we don't know
01282    what to close then.  */
01283 typedef struct quotation_elt
01284 {
01285   struct quotation_elt *next;
01286   char *type;
01287 } QUOTATION_ELT;
01288 
01289 static QUOTATION_ELT *quotation_stack = NULL;
01290 
01291 void
01292 xml_insert_quotation (char *type, int arg)
01293 {
01294   int quotation_started = 0;
01295 
01296   if (arg == START)
01297     {
01298       QUOTATION_ELT *new = xmalloc (sizeof (QUOTATION_ELT));
01299       new->type = xstrdup (type);
01300       new->next = quotation_stack;
01301       quotation_stack = new;
01302     }
01303   else
01304     type = quotation_stack->type;
01305 
01306   /* Make use of special quotation styles of Docbook if we can.  */
01307   if (docbook && strlen(type))
01308     {
01309       /* Let's assume it started.  */
01310       quotation_started = 1;
01311 
01312       if (strcasecmp (type, "tip") == 0)
01313         xml_insert_element (TIP, arg);
01314       else if (strcasecmp (type, "note") == 0)
01315         xml_insert_element (NOTE, arg);
01316       else if (strcasecmp (type, "important") == 0)
01317         xml_insert_element (IMPORTANT, arg);
01318       else if (strcasecmp (type, "warning") == 0)
01319         xml_insert_element (WARNING, arg);
01320       else if (strcasecmp (type, "caution") == 0)
01321         xml_insert_element (CAUTION, arg);
01322       else
01323         /* Didn't find a known quotation type :\ */
01324         quotation_started = 0;
01325     }
01326 
01327   if (!quotation_started)
01328     {
01329       xml_insert_element (QUOTATION, arg);
01330       if (strlen(type) && arg == START)
01331         execute_string ("@b{%s:} ", type);
01332     }
01333 
01334   if (arg == END)
01335     {
01336       QUOTATION_ELT *temp = quotation_stack;
01337       if (temp == NULL)
01338         return;
01339       quotation_stack = quotation_stack->next;
01340       free(temp->type);
01341       free(temp);
01342     }
01343 }
01344 
01345 /* Starting generic docbook floats.  Just starts elt with correct label
01346    and id attributes, and inserts title.  */
01347 void
01348 xml_begin_docbook_float (int elt)
01349 {
01350   if (current_float_used_title ()) /* in a nested float */
01351     {
01352       xml_insert_element (elt, START);    /* just insert the tag */
01353       return;
01354     }
01355 
01356 
01357   /* OK, need the title, tag, etc. */
01358   if (elt == CARTOUCHE)    /* no labels on <sidebar> */
01359     {
01360        if (strlen (current_float_id ()) == 0)
01361           xml_insert_element (elt, START);
01362        else
01363           xml_insert_element_with_attribute (elt, START,
01364               "id=\"%s\"", xml_id (current_float_id ()));
01365     }
01366   else if (strlen (current_float_id ()) == 0)
01367     xml_insert_element_with_attribute (elt, START, "label=\"\"");
01368   else
01369     xml_insert_element_with_attribute (elt, START,
01370         "id=\"%s\" label=\"%s\"", xml_id (current_float_id ()),
01371         current_float_number ());
01372 
01373   xml_insert_element (TITLE, START);
01374   execute_string ("%s", current_float_title ());
01375   xml_insert_element (TITLE, END);
01376 
01377   current_float_set_title_used (); /* mark this title, tag, etc used */
01378 }
01379 
01380 /*
01381  * Lists and Tables
01382  */
01383 void
01384 xml_begin_table (int type, char *item_function)
01385 {
01386   switch (type)
01387     {
01388     case ftable:
01389     case vtable:
01390     case table:
01391       /*if (docbook)*/ /* 05-08 */
01392         {
01393           xml_insert_element (TABLE, START);
01394           xml_table_level ++;
01395           xml_in_tableitem[xml_table_level] = 0;
01396           xml_in_item[xml_table_level] = 0;
01397           xml_after_table_term = 0;
01398         }
01399       break;
01400     case itemize:
01401       if (!docbook)
01402         {
01403           xml_insert_element (ITEMIZE, START);
01404           xml_table_level ++;
01405           xml_in_item[xml_table_level] = 0;
01406           xml_insert_element (ITEMFUNCTION, START);
01407           if (*item_function == COMMAND_PREFIX
01408               && item_function[strlen (item_function) - 1] != '}'
01409               && command_needs_braces (item_function + 1))
01410             execute_string ("%s{}", item_function);
01411           else
01412             execute_string ("%s", item_function);
01413           xml_insert_element (ITEMFUNCTION, END);
01414         }
01415       else
01416         {
01417           xml_insert_element_with_attribute (ITEMIZE, START,
01418                                              "mark=\"%s\"",
01419                                              (*item_function == COMMAND_PREFIX) ?
01420                                              &item_function[1] : item_function);
01421           xml_table_level ++;
01422           xml_in_item[xml_table_level] = 0;
01423         }
01424       break;
01425     }
01426 }
01427 
01428 void
01429 xml_end_table (int type)
01430 {
01431   switch (type)
01432     {
01433     case ftable:
01434     case vtable:
01435     case table:
01436       if (xml_in_item[xml_table_level])
01437         {
01438           xml_insert_element (ITEM, END);
01439           xml_in_item[xml_table_level] = 0;
01440         }
01441       if (xml_in_tableitem[xml_table_level])
01442         {
01443           xml_insert_element (TABLEITEM, END);
01444           xml_in_tableitem[xml_table_level] = 0;
01445         }
01446       xml_insert_element (TABLE, END);
01447       xml_after_table_term = 0;
01448       xml_table_level --;
01449 
01450       break;
01451     case itemize:
01452       if (xml_in_item[xml_table_level])
01453         {
01454           xml_insert_element (ITEM, END);
01455           xml_in_item[xml_table_level] = 0;
01456         }
01457       /* gnat-style manual contains an itemized list without items! */
01458       if (in_table_title)
01459        {
01460          xml_insert_element (TITLE, END);
01461          in_table_title = 0;
01462        }
01463       xml_insert_element (ITEMIZE, END);
01464       xml_table_level --;
01465       break;
01466     }
01467 }
01468 
01469 void
01470 xml_begin_item (void)
01471 {
01472   if (xml_in_item[xml_table_level])
01473     xml_insert_element (ITEM, END);
01474 
01475   xml_insert_element (ITEM, START);
01476   xml_in_item[xml_table_level] = 1;
01477 }
01478 
01479 void
01480 xml_begin_table_item (void)
01481 {
01482   if (!xml_after_table_term)
01483     {
01484       if (xml_in_item[xml_table_level])
01485         xml_insert_element (ITEM, END);
01486       if (xml_in_tableitem[xml_table_level])
01487         xml_insert_element (TABLEITEM, END);
01488 
01489       if (in_table_title)
01490        {
01491          in_table_title = 0;
01492          xml_insert_element (TITLE, END);
01493        }
01494       xml_insert_element (TABLEITEM, START);
01495     }
01496   xml_insert_element (TABLETERM, START);
01497   xml_in_tableitem[xml_table_level] = 1;
01498   xml_in_item[xml_table_level] = 0;
01499   xml_after_table_term = 0;
01500 }
01501 
01502 void
01503 xml_continue_table_item (void)
01504 {
01505   xml_insert_element (TABLETERM, END);
01506   xml_after_table_term = 1;
01507   xml_in_item[xml_table_level] = 0;
01508 }
01509 
01510 void
01511 xml_begin_enumerate (char *enum_arg)
01512 {
01513   if (!docbook)
01514     xml_insert_element_with_attribute (ENUMERATE, START, "first=\"%s\"", enum_arg);
01515   else
01516     {
01517       if (isdigit (*enum_arg))
01518         {
01519           int enum_val = atoi (enum_arg);
01520 
01521           /* Have to check the value, not just the first digit.  */
01522           if (enum_val == 0)
01523             xml_insert_element_with_attribute (ENUMERATE, START,
01524                 "numeration=\"arabic\" role=\"0\"", NULL);
01525           else if (enum_val == 1)
01526             xml_insert_element_with_attribute (ENUMERATE, START,
01527                 "numeration=\"arabic\"", NULL);
01528           else
01529             xml_insert_element_with_attribute (ENUMERATE, START,
01530                 "continuation=\"continues\" numeration=\"arabic\"", NULL);
01531         }
01532       else if (isupper (*enum_arg))
01533         {
01534           if (enum_arg[0] == 'A')
01535             xml_insert_element_with_attribute (ENUMERATE, START,
01536                 "numeration=\"upperalpha\"", NULL);
01537           else
01538             xml_insert_element_with_attribute (ENUMERATE, START,
01539                 "continuation=\"continues\" numeration=\"upperalpha\"", NULL);
01540         }
01541       else
01542         {
01543           if (enum_arg[0] == 'a')
01544             xml_insert_element_with_attribute (ENUMERATE, START,
01545                 "numeration=\"loweralpha\"", NULL);
01546           else
01547             xml_insert_element_with_attribute (ENUMERATE, START,
01548                 "continuation=\"continues\" numeration=\"loweralpha\"", NULL);
01549         }
01550     }
01551   xml_table_level ++;
01552   xml_in_item[xml_table_level] = 0;
01553 }
01554 
01555 void
01556 xml_end_enumerate (void)
01557 {
01558   if (xml_in_item[xml_table_level])
01559     {
01560       xml_insert_element (ITEM, END);
01561       xml_in_item[xml_table_level] = 0;
01562     }
01563   xml_insert_element (ENUMERATE, END);
01564   xml_table_level --;
01565 }
01566 
01567 static void
01568 xml_insert_text_file (char *name_arg)
01569 {
01570   char *fullname = xmalloc (strlen (name_arg) + 4 + 1);
01571   FILE *image_file;
01572   strcpy (fullname, name_arg);
01573   strcat (fullname, ".txt");
01574   image_file = fopen (fullname, "r");
01575   if (image_file)
01576     {
01577       int ch;
01578       int save_inhibit_indentation = inhibit_paragraph_indentation;
01579       int save_filling_enabled = filling_enabled;
01580 
01581       xml_insert_element (TEXTOBJECT, START);
01582       xml_insert_element (DISPLAY, START);
01583 
01584       inhibit_paragraph_indentation = 1;
01585       filling_enabled = 0;
01586       last_char_was_newline = 0;
01587 
01588       /* Maybe we need to remove the final newline if the image
01589          file is only one line to allow in-line images.  On the
01590          other hand, they could just make the file without a
01591          final newline.  */
01592       while ((ch = getc (image_file)) != EOF)
01593         add_char (ch);
01594 
01595       inhibit_paragraph_indentation = save_inhibit_indentation;
01596       filling_enabled = save_filling_enabled;
01597 
01598       xml_insert_element (DISPLAY, END);
01599       xml_insert_element (TEXTOBJECT, END);
01600 
01601       if (fclose (image_file) != 0)
01602         perror (fullname);
01603     }
01604   else
01605     warning (_("@image file `%s' unreadable: %s"), fullname,
01606              strerror (errno));
01607 
01608   free (fullname);
01609 }
01610 
01611 /* If NAME.EXT is accessible or FORCE is nonzero, insert a docbook
01612    imagedata element for FMT.  Return 1 if inserted something, 0 else.  */
01613 
01614 static int
01615 try_docbook_image (const char *name, const char *ext, const char *fmt,
01616                    int force)
01617 {
01618   int used = 0;
01619   char *fullname = xmalloc (strlen (name) + 1 + strlen (ext) + 1);
01620   sprintf (fullname, "%s.%s", name, ext);
01621 
01622   if (force || access (fullname, R_OK) == 0)
01623    {
01624      xml_insert_element (IMAGEOBJECT, START);
01625      xml_insert_element_with_attribute (IMAGEDATA, START,
01626        "fileref=\"%s\" format=\"%s\"", fullname, fmt);
01627      xml_insert_element (IMAGEDATA, END);
01628      xml_insert_element (IMAGEOBJECT, END);
01629      used = 1;
01630    }
01631  
01632  free (fullname);
01633  return used;
01634 }
01635 
01636 
01637 void
01638 xml_insert_docbook_image (char *name_arg)
01639 {
01640   int found = 0;
01641   int elt = xml_in_para ? INLINEIMAGE : MEDIAOBJECT;
01642 
01643   if (is_in_insertion_of_type (floatenv))
01644     xml_begin_docbook_float (INFORMALFIGURE);
01645   else if (!xml_in_para)
01646     xml_insert_element (INFORMALFIGURE, START);
01647 
01648   xml_no_para++;
01649 
01650   xml_insert_element (elt, START);
01651 
01652   /* A selected few from http://docbook.org/tdg/en/html/imagedata.html.  */
01653   if (try_docbook_image (name_arg, "eps", "EPS", 0))
01654     found++;
01655   if (try_docbook_image (name_arg, "gif", "GIF", 0))
01656     found++;
01657   if (try_docbook_image (name_arg, "jpg", "JPG", 0))
01658     found++;
01659   if (try_docbook_image (name_arg, "jpeg", "JPEG", 0))
01660     found++;
01661   if (try_docbook_image (name_arg, "pdf", "PDF", 0))
01662     found++;
01663   if (try_docbook_image (name_arg, "png", "PNG", 0))
01664     found++;
01665   if (try_docbook_image (name_arg, "svg", "SVG", 0))
01666     found++;
01667 
01668   /* If no luck so far, just assume we'll eventually have a jpg.  */
01669   if (!found)
01670     try_docbook_image (name_arg, "jpg", "JPG", 1);
01671  
01672   xml_insert_text_file (name_arg);
01673   xml_insert_element (elt, END);
01674 
01675   xml_no_para--;
01676 
01677   if (elt == MEDIAOBJECT)
01678     xml_insert_element (INFORMALFIGURE, END);
01679 }
01680 
01681 void
01682 xml_asterisk (void)
01683 {
01684 }
01685 
01686 
01687 /*
01688  *     INDEX
01689  */
01690 /* Used to separate primary and secondary entries in an index -- we need
01691    to have real multilivel indexing support, not just string analysis.  */
01692 #define INDEX_SEP "@this string will never appear@" /* was , */
01693 
01694 typedef struct
01695 {
01696   char *from;
01697   char *to;
01698 } XML_SYNONYM;
01699 
01700 static XML_SYNONYM **xml_synonyms = NULL;
01701 static int xml_synonyms_count = 0;
01702 
01703 void
01704 xml_insert_indexterm (char *indexterm, char *index)
01705 {
01706   /* @index commands can appear between @item and @itemx, @deffn and @deffnx.  */
01707   if (!docbook)
01708     {
01709       /* Check to see if we need to do index redirection per @synindex.  */
01710       int i;
01711       for (i = 0; i < xml_synonyms_count; i++)
01712         {
01713           if (STREQ (xml_synonyms[i]->from, index))
01714             index = xstrdup (xml_synonyms[i]->to);
01715         }
01716 
01717       xml_dont_touch_items_defs++;
01718       xml_insert_element_with_attribute (INDEXTERM, START, "index=\"%s\"", index);
01719       in_indexterm = 1;
01720       execute_string ("%s", indexterm);
01721       xml_insert_element (INDEXTERM, END);
01722       in_indexterm = 0;
01723       xml_dont_touch_items_defs--;
01724     }
01725   else
01726     {
01727       char *primary = NULL, *secondary = NULL;
01728       if (strstr (indexterm+1, INDEX_SEP))
01729         {
01730           primary = xmalloc (strlen (indexterm) + 1);
01731           strcpy (primary, indexterm);
01732           secondary = strstr (primary+1, INDEX_SEP);
01733           *secondary = '\0';
01734           secondary += strlen (INDEX_SEP);
01735         }
01736       xml_insert_element_with_attribute (INDEXTERM, START, "role=\"%s\"", index);
01737       in_indexterm = 1;
01738       xml_insert_element (PRIMARY, START);
01739       if (primary)
01740         execute_string ("%s", primary);
01741       else
01742         execute_string ("%s", indexterm);
01743       xml_insert_element (PRIMARY, END);
01744       if (primary)
01745         {
01746           xml_insert_element (SECONDARY, START);
01747           execute_string ("%s", secondary);
01748           xml_insert_element (SECONDARY, END);
01749         }
01750       xml_insert_element (INDEXTERM, END);
01751       in_indexterm = 0;
01752     }
01753 }
01754 
01755 
01756 int xml_last_section_output_position = 0;
01757 static char last_division_letter = ' ';
01758 static char index_primary[2000]; 
01759 static int indexdivempty = 0;
01760 
01761 static void
01762 xml_close_indexentry (void)
01763 {
01764   if (!in_indexentry)
01765     return;
01766   if (in_secondary)
01767     xml_insert_element (SECONDARYIE, END);
01768   xml_insert_element (INDEXENTRY, END);
01769   in_secondary = 0;
01770   in_indexentry = 0;
01771 }
01772 
01773 void
01774 xml_begin_index (void)
01775 {
01776   typedef struct xml_index_title {
01777       struct xml_index_title *next;
01778       char *title;
01779   } XML_INDEX_TITLE;
01780 
01781   static XML_INDEX_TITLE *xml_index_titles = NULL;
01782 
01783   if (!handling_delayed_writes)
01784     { /* We assume that we just opened a section, and so that the last output is
01785          <SECTION ID="node-name"><TITLE>Title</TITLE>
01786          where SECTION can be CHAPTER, ...  */
01787 
01788       XML_INDEX_TITLE *new = xmalloc (sizeof (XML_INDEX_TITLE));
01789       xml_section *temp = last_section;
01790 
01791       int l = output_paragraph_offset-xml_last_section_output_position;
01792       char *tmp = xmalloc (l+1);
01793       char *p = tmp;
01794       strncpy (tmp, (char *) output_paragraph, l);
01795 
01796       /* We remove <SECTION */
01797       tmp[l] = '\0';
01798       while (*p != '<')
01799         p++;
01800       while (*p != ' ')
01801         p++;
01802       /* ... and its label attribute.  */
01803       if (strncmp (p, " label=", 7) == 0)
01804         {
01805           p++;
01806           while (*p != ' ')
01807             p++;
01808         }
01809 
01810       output_paragraph_offset = xml_last_section_output_position;
01811       xml_last_section_output_position = 0;
01812 
01813       xml_pop_current_element (); /* remove section element from elements stack */
01814 
01815       if (last_section)
01816         last_section = last_section->prev; /* remove section from sections stack */
01817       if (temp)
01818         {
01819           free (temp->name);
01820           free (temp);
01821         }
01822 
01823       new->title = xstrdup (p);
01824       new->next = xml_index_titles;
01825       xml_index_titles = new;
01826     }
01827   else
01828     {
01829       static int xml_index_titles_reversed = 0;
01830 
01831       if (!xml_index_titles_reversed)
01832         {
01833           xml_index_titles = (XML_INDEX_TITLE *) reverse_list
01834             ((GENERIC_LIST *) xml_index_titles);
01835           xml_index_titles_reversed = 1;
01836         }
01837 
01838       /* We put <INDEX> */
01839       xml_insert_element (PRINTINDEX, START);
01840       if (xml_index_titles)
01841         {
01842           /* Remove the final > */
01843           output_paragraph_offset--;
01844           /* and put  ID="node-name"><TITLE>Title</TITLE> */
01845           insert_string (xml_index_titles->title);
01846           free (xml_index_titles->title);
01847           xml_index_titles = xml_index_titles->next;
01848         }
01849 
01850       if (xml_index_divisions)
01851         {
01852           xml_insert_element (INDEXDIV, START);
01853           indexdivempty = 1;
01854         }
01855     }
01856 }
01857 
01858 void
01859 xml_end_index (void)
01860 {
01861   xml_close_indexentry ();
01862   if (xml_index_divisions)
01863     xml_insert_element (INDEXDIV, END);
01864   xml_insert_element (PRINTINDEX, END);
01865 }
01866 
01867 static void
01868 xml_index_divide (char *entry)
01869 {
01870   char c;
01871   if (strlen (entry) > (strlen (xml_element_list[CODE].name) + 2) &&
01872       strncmp (entry+1, xml_element_list[CODE].name, strlen (xml_element_list[CODE].name)) == 0)
01873     c = entry[strlen (xml_element_list[CODE].name)+2];
01874   else
01875     c = entry[0];
01876   if (tolower (c) != last_division_letter && isalpha (c))
01877     {
01878       last_division_letter = tolower (c);
01879       xml_close_indexentry ();
01880       if (!indexdivempty)
01881         {
01882           xml_insert_element (INDEXDIV, END);
01883           xml_insert_element (INDEXDIV, START);
01884         }
01885       xml_insert_element (TITLE, START);
01886       insert (toupper (c));
01887       xml_insert_element (TITLE, END);
01888     }
01889 }
01890 
01891 void
01892 xml_insert_indexentry (char *entry, char *node)
01893 {
01894   char *primary = NULL, *secondary;
01895   if (xml_index_divisions)
01896     xml_index_divide (entry);
01897 
01898   indexdivempty = 0;
01899   if (strstr (entry+1, INDEX_SEP))
01900     {
01901       primary = xmalloc (strlen (entry) + 1);
01902       strcpy (primary, entry);
01903       secondary = strstr (primary+1, INDEX_SEP);
01904       *secondary = '\0';
01905       secondary += strlen (INDEX_SEP);
01906 
01907       if (in_secondary && strcmp (primary, index_primary) == 0)
01908         {
01909           xml_insert_element (SECONDARYIE, END);
01910           xml_insert_element (SECONDARYIE, START);
01911           execute_string ("%s", secondary);
01912         }
01913       else
01914         {
01915           xml_close_indexentry ();
01916           xml_insert_element (INDEXENTRY, START);
01917           in_indexentry = 1;
01918           xml_insert_element (PRIMARYIE, START);
01919           execute_string ("%s", primary);
01920           xml_insert_element (PRIMARYIE, END);
01921           xml_insert_element (SECONDARYIE, START);
01922           execute_string ("%s", secondary);
01923           in_secondary = 1;
01924         }
01925     }
01926   else
01927     {
01928       xml_close_indexentry ();
01929       xml_insert_element (INDEXENTRY, START);
01930       in_indexentry = 1;
01931       xml_insert_element (PRIMARYIE, START);
01932       execute_string ("%s", entry);
01933     }
01934   add_word (", ");
01935 
01936   /* Don't link to @unnumbered sections directly.
01937      We are disabling warnings temporarily, otherwise these xrefs
01938      will cause bogus warnings about missing punctuation.  */
01939   {
01940     extern int print_warnings;
01941     int save_print_warnings = print_warnings;
01942     print_warnings = 0;
01943     execute_string ("%cxref{%s}", COMMAND_PREFIX, xstrdup (node));
01944     print_warnings = save_print_warnings;
01945   }
01946 
01947   if (primary)
01948     {
01949       strcpy (index_primary, primary);
01950       /*      xml_insert_element (SECONDARYIE, END);*/
01951       /*     *(secondary-1) = ',';*/ /* necessary ? */
01952       free (primary);
01953     }
01954   else
01955     xml_insert_element (PRIMARYIE, END);
01956 
01957   /*  xml_insert_element (INDEXENTRY, END); */
01958 }
01959 
01960 void
01961 xml_synindex (char *from, char *to)
01962 {
01963   int i, slot;
01964 
01965   slot = -1;
01966   for (i = 0; i < xml_synonyms_count; i++)
01967     if (!xml_synonyms[i])
01968       {
01969         slot = i;
01970         break;
01971       }
01972 
01973   if (slot < 0)
01974     {
01975       slot = xml_synonyms_count;
01976       xml_synonyms_count++;
01977 
01978       xml_synonyms = (XML_SYNONYM **) xrealloc (xml_synonyms,
01979           (xml_synonyms_count + 1) * sizeof (XML_SYNONYM *));
01980     }
01981 
01982   xml_synonyms[slot] = xmalloc (sizeof (XML_SYNONYM));
01983   xml_synonyms[slot]->from = xstrdup (from);
01984   xml_synonyms[slot]->to = xstrdup (to);
01985 }
01986 
01987 /*
01988  * MULTITABLE
01989  */
01990 
01991 static int multitable_columns_count;
01992 static int *multitable_column_widths;
01993 
01994 void
01995 xml_begin_multitable (int ncolumns, int *column_widths)
01996 {
01997   int i;
01998   if (docbook)
01999     {
02000       if (is_in_insertion_of_type (floatenv))
02001         xml_begin_docbook_float (MULTITABLE);
02002       else
02003         xml_insert_element (MULTITABLE, START);
02004 
02005       multitable_columns_count = ncolumns;
02006       multitable_column_widths = xmalloc (sizeof (int) * ncolumns);
02007       memcpy (multitable_column_widths, column_widths,
02008           sizeof (int) * ncolumns);
02009 
02010       xml_no_para = 1;
02011     }
02012   else
02013     {
02014       xml_insert_element (MULTITABLE, START);
02015       for (i=0; i<ncolumns; i++)
02016         {
02017           xml_insert_element (COLSPEC, START);
02018           add_word_args ("%d", column_widths[i]);
02019           xml_insert_element (COLSPEC, END);
02020         }
02021       xml_no_para = 1;
02022     }
02023 }
02024 
02025 static void
02026 xml_begin_multitable_group (void)
02027 {
02028   int i;
02029 
02030   xml_insert_element_with_attribute (TGROUP, START, "cols=\"%d\"",
02031       multitable_columns_count);
02032 
02033   for (i=0; i < multitable_columns_count; i++)
02034     {
02035       xml_insert_element_with_attribute (COLSPEC, START,
02036           "colwidth=\"%d*\"", multitable_column_widths[i]);
02037       xml_insert_element (COLSPEC, END);
02038     }
02039 }
02040 
02041 void
02042 xml_end_multitable_row (int first_row)
02043 {
02044   if (!first_row)
02045     {
02046       xml_insert_element (ENTRY, END);
02047       xml_insert_element (ROW, END);
02048     }
02049 
02050   if (headitem_flag)
02051     {
02052       if (!first_row)
02053         {
02054           if (after_headitem)
02055             xml_insert_element (THEAD, END);
02056           else
02057             xml_insert_element (TBODY, END);
02058           xml_insert_element (TGROUP, END);
02059         }
02060 
02061       xml_begin_multitable_group ();
02062       xml_insert_element (THEAD, START);
02063     }
02064   else if (first_row)
02065     {
02066       xml_begin_multitable_group ();
02067       xml_insert_element (TBODY, START);
02068     }
02069   else if (after_headitem)
02070     {
02071       xml_insert_element (THEAD, END);
02072       xml_insert_element (TBODY, START);
02073     }
02074   else if (first_row)
02075     xml_insert_element (TBODY, START);
02076 
02077   xml_insert_element (ROW, START);
02078   xml_insert_element (ENTRY, START);
02079 }
02080 
02081 void
02082 xml_end_multitable_column (void)
02083 {
02084   xml_insert_element (ENTRY, END);
02085   xml_insert_element (ENTRY, START);
02086 }
02087 
02088 void
02089 xml_end_multitable (void)
02090 {
02091   xml_insert_element (ENTRY, END);
02092   xml_insert_element (ROW, END);
02093 
02094   if (after_headitem)
02095     {
02096       if (docbook)
02097         warning (_("@headitem as the last item of @multitable produces invalid Docbook documents"));
02098       xml_insert_element (THEAD, END);
02099     }
02100   else
02101     xml_insert_element (TBODY, END);
02102 
02103   if (docbook)
02104     xml_insert_element (TGROUP, END);
02105 
02106   xml_insert_element (MULTITABLE, END);
02107   xml_no_para = 0;
02108 }
02109 
02110 /*
02111  * Parameters in @def definitions
02112  */
02113 
02114 #define DEFUN_SELF_DELIMITING(c) \
02115   ((c) == '(' || (c) == ')' || (c) == '[' || (c) == ']')
02116 
02117 void
02118 xml_process_defun_args (char **defun_args, int auto_var_p)
02119 {
02120   int pending_space = 0;
02121   int just_after_paramtype = 0;
02122 
02123   for (;;)
02124     {
02125       char *defun_arg = *defun_args++;
02126 
02127       if (defun_arg == NULL)
02128         break;
02129 
02130       if (defun_arg[0] == ' ')
02131         {
02132           pending_space = 1;
02133           continue;
02134         }
02135 
02136       if (pending_space)
02137         {
02138           add_char (' ');
02139           pending_space = 0;
02140         }
02141 
02142       if (DEFUN_SELF_DELIMITING (defun_arg[0]))
02143         {
02144          xml_insert_element (DEFDELIMITER, START);
02145           add_char (defun_arg[0]);
02146          xml_insert_element (DEFDELIMITER, END);
02147          just_after_paramtype = 0;
02148         }
02149       else if (defun_arg[0] == '&')
02150        {
02151          xml_insert_element (DEFPARAM, START);
02152          add_word (defun_arg);
02153          xml_insert_element (DEFPARAM, END);
02154          just_after_paramtype = 0;
02155        }
02156       else if (defun_arg[0] == COMMAND_PREFIX || just_after_paramtype)
02157        {
02158          xml_insert_element (DEFPARAM, START);
02159          execute_string ("%s", defun_arg);
02160          xml_insert_element (DEFPARAM, END);
02161          just_after_paramtype = 0;
02162        }
02163       else if (defun_arg[0] == ',' || defun_arg[0] == ';')
02164        {
02165          xml_insert_element (DEFDELIMITER, START);
02166          add_word (defun_arg);
02167          xml_insert_element (DEFDELIMITER, END);
02168          just_after_paramtype = 0;
02169        }
02170       else if (auto_var_p)
02171        {
02172          xml_insert_element (DEFPARAM, START);
02173          add_word (defun_arg);
02174          xml_insert_element (DEFPARAM, END);
02175          just_after_paramtype = 0;
02176        }
02177       else
02178        {
02179          xml_insert_element (DEFPARAMTYPE, START);
02180          add_word (defun_arg);
02181          xml_insert_element (DEFPARAMTYPE, END);
02182          just_after_paramtype = 1;
02183        }
02184     }
02185 }
02186 
02187 void
02188 xml_begin_definition (void)
02189 {
02190   xml_insert_element (DEFINITION, START);
02191   xml_definition_level ++;
02192   xml_in_def_item[xml_definition_level] = 0;
02193 }
02194 
02195 void
02196 xml_end_definition (void)
02197 {
02198   if (xml_in_def_item[xml_definition_level])
02199     {
02200       xml_insert_element (DEFINITIONITEM, END);
02201       xml_in_def_item[xml_definition_level] = 0;
02202     }
02203   xml_after_def_term = 0;
02204   xml_insert_element (DEFINITION, END);
02205   xml_definition_level --;
02206 }
02207 
02208 void
02209 xml_begin_def_term (int base_type, const char *category,
02210     char *defined_name, char *type_name, char *type_name2)
02211 {
02212   xml_after_def_term = 0;
02213   xml_insert_element (DEFINITIONTERM, START);
02214 
02215   /* Index entry */
02216   switch (base_type)
02217     {
02218     case deffn:
02219     case deftypefn:
02220       execute_string ("@findex %s\n", defined_name);
02221       break;
02222     case defvr:
02223     case deftypevr:
02224     case defcv:
02225       execute_string ("@vindex %s\n", defined_name);
02226       break;
02227     case deftypecv:
02228     case deftypeivar:
02229       execute_string ("@vindex %s %s %s\n", defined_name, _("of"), type_name);
02230       break;
02231     case deftypemethod:
02232     case defop:
02233     case deftypeop:
02234       execute_string ("@findex %s %s %s\n", defined_name, _("on"), type_name);
02235       break;
02236     case deftp:
02237       execute_string ("@tindex %s\n", defined_name);
02238       break;
02239     }
02240 
02241   /* Start with category.  */
02242   xml_insert_element (DEFCATEGORY, START);
02243   execute_string (docbook ? "--- %s:" : "%s", category);
02244   xml_insert_element (DEFCATEGORY, END);
02245   add_char(' ');
02246 
02247   /* Output type name first for typed definitions.  */
02248   switch (base_type)
02249     {
02250     case deffn:
02251     case defvr:
02252     case deftp:
02253       break;
02254 
02255     case deftypefn:
02256     case deftypevr:
02257       xml_insert_element (DEFTYPE, START);
02258       execute_string ("%s", type_name);
02259       xml_insert_element (DEFTYPE, END);
02260       add_char (' ');
02261       break;
02262 
02263     case deftypecv:
02264     case deftypeivar:
02265     case deftypemethod:
02266     case deftypeop:
02267       xml_insert_element (DEFTYPE, START);
02268       execute_string ("%s", type_name2);
02269       xml_insert_element (DEFTYPE, END);
02270       add_char (' ');
02271       break;
02272 
02273     default:
02274       xml_insert_element (DEFCLASS, START);
02275       execute_string ("%s", type_name);
02276       xml_insert_element (DEFCLASS, END);
02277       add_char (' ');
02278       break;
02279     }
02280 
02281   /* Categorize rest of the definitions.  */
02282   switch (base_type)
02283     {
02284     case deffn:
02285     case deftypefn:
02286       xml_insert_element (DEFFUNCTION, START);
02287       execute_string ("%s", defined_name);
02288       xml_insert_element (DEFFUNCTION, END);
02289       break;
02290 
02291     case defvr:
02292     case deftypevr:
02293       xml_insert_element (DEFVARIABLE, START);
02294       execute_string ("%s", defined_name);
02295       xml_insert_element (DEFVARIABLE, END);
02296       break;
02297 
02298     case deftp:
02299       xml_insert_element (DEFDATATYPE, START);
02300       execute_string ("%s", defined_name);
02301       xml_insert_element (DEFDATATYPE, END);
02302       break;
02303 
02304     case defcv:
02305     case deftypecv:
02306     case deftypeivar:
02307       xml_insert_element (DEFCLASSVAR, START);
02308       execute_string ("%s", defined_name);
02309       xml_insert_element (DEFCLASSVAR, END);
02310       break;
02311 
02312     case defop:
02313     case deftypeop:
02314     case deftypemethod:
02315       /* Operation / Method */
02316       xml_insert_element (DEFOPERATION, START);
02317       execute_string ("%s", defined_name);
02318       xml_insert_element (DEFOPERATION, END);
02319       break;
02320     }
02321 }
02322 
02323 void
02324 xml_end_def_term (void)
02325 {
02326   xml_insert_element (DEFINITIONTERM, END);
02327   xml_after_def_term = 1;
02328 }