/* xml.c -- xml output. $Id: xml.c,v 1.52 2004/12/19 17:02:23 karl Exp $ Copyright (C) 2001, 2002, 2003, 2004 Free Software Foundation, Inc. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. Originally written by Philippe Martin . */ #include "system.h" #include "makeinfo.h" #include "insertion.h" #include "files.h" #include "float.h" #include "macro.h" #include "cmds.h" #include "lang.h" #include "xml.h" /* Options */ int xml_index_divisions = 1; typedef struct _element { char name[32]; int contains_para; int contained_in_para; int keep_space; } element; element texinfoml_element_list [] = { { "texinfo", 1, 0, 0 }, { "setfilename", 0, 0, 0 }, { "titlefont", 0, 0, 0 }, { "settitle", 0, 0, 0 }, { "documentdescription", 1, 0, 0 }, { "node", 1, 0, 0 }, { "nodenext", 0, 0, 0 }, { "nodeprev", 0, 0, 0 }, { "nodeup", 0, 0, 0 }, { "chapter", 1, 0, 0 }, { "section", 1, 0, 0 }, { "subsection", 1, 0, 0 }, { "subsubsection", 1, 0, 0 }, { "top", 1, 0, 0 }, { "unnumbered", 1, 0, 0 }, { "unnumberedsec", 1, 0, 0 }, { "unnumberedsubsec", 1, 0, 0 }, { "unnumberedsubsubsec", 1, 0, 0 }, { "appendix", 1, 0, 0 }, { "appendixsec", 1, 0, 0 }, { "appendixsubsec", 1, 0, 0 }, { "appendixsubsubsec", 1, 0, 0 }, { "majorheading", 0, 0, 0 }, { "chapheading", 0, 0, 0 }, { "heading", 0, 0, 0 }, { "subheading", 0, 0, 0 }, { "subsubheading", 0, 0, 0 }, { "titlepage", 1, 0, 0 }, { "author", 0, 0, 0 }, { "booktitle", 0, 0, 0 }, { "booksubtitle", 0, 0, 0 }, { "menu", 1, 0, 0 }, { "detailmenu", 1, 0, 0 }, { "menuentry", 0, 0, 0 }, { "menutitle", 0, 0, 0 }, { "menucomment", 0, 0, 0 }, { "menunode", 0, 0, 0 }, { "nodename", 0, 0, 0 }, { "acronym", 0, 1, 0 }, { "acronymword", 0, 1, 0 }, { "acronymdesc", 0, 1, 0 }, { "abbrev", 0, 1, 0 }, { "abbrevword", 0, 1, 0 }, { "abbrevdesc", 0, 1, 0 }, { "tt", 0, 1, 0 }, { "code", 0, 1, 0 }, { "command", 0, 1, 0 }, { "env", 0, 1, 0 }, { "file", 0, 1, 0 }, { "option", 0, 1, 0 }, { "samp", 0, 1, 0 }, { "kbd", 0, 1, 0 }, { "url", 0, 1, 0 }, { "key", 0, 1, 0 }, { "var", 0, 1, 0 }, { "sc", 0, 1, 0 }, { "dfn", 0, 1, 0 }, { "emph", 0, 1, 0 }, { "strong", 0, 1, 0 }, { "cite", 0, 1, 0 }, { "notfixedwidth", 0, 1, 0 }, { "i", 0, 1, 0 }, { "b", 0, 1, 0 }, { "r", 0, 1, 0 }, { "slanted", 0, 1, 0 }, { "sansserif", 0, 1, 0 }, { "exdent", 0, 0, 0 }, { "title", 0, 0, 0 }, { "ifinfo", 1, 0, 0 }, { "sp", 0, 0, 0 }, { "center", 1, 0, 0 }, { "dircategory", 0, 0, 0 }, { "quotation", 1, 0, 0 }, { "example", 0, 0, 1 }, { "smallexample", 0, 0, 1 }, { "lisp", 0, 0, 1 }, { "smalllisp", 0, 0, 1 }, { "cartouche", 1, 0, 0 }, { "copying", 1, 0, 0 }, { "format", 0, 0, 1 }, { "smallformat", 0, 0, 1 }, { "display", 0, 0, 1 }, { "smalldisplay", 0, 0, 1 }, { "verbatim", 0, 0, 1 }, { "footnote", 0, 1, 0 }, { "", 0, 1, 0 }, /* LINEANNOTATION (docbook) */ { "", 1, 0, 0 }, /* TIP (docbook) */ { "", 1, 0, 0 }, /* NOTE (docbook) */ { "", 1, 0, 0 }, /* IMPORTANT (docbook) */ { "", 1, 0, 0 }, /* WARNING (docbook) */ { "", 1, 0, 0 }, /* CAUTION (docbook) */ { "itemize", 0, 0, 0 }, { "itemfunction", 0, 0, 0 }, { "item", 1, 0, 0 }, { "enumerate", 0, 0, 0 }, { "table", 0, 0, 0 }, { "tableitem", 0, 0, 0 }, { "tableterm", 0, 0, 0 }, { "indexterm", 0, 1, 0 }, { "math", 0, 1, 0 }, { "dmn", 0, 1, 0 }, { "xref", 0, 1, 0 }, { "xrefnodename", 0, 1, 0 }, { "xrefinfoname", 0, 1, 0 }, { "xrefprinteddesc", 0, 1, 0 }, { "xrefinfofile", 0, 1, 0 }, { "xrefprintedname", 0, 1, 0 }, { "inforef", 0, 1, 0 }, { "inforefnodename", 0, 1, 0 }, { "inforefrefname", 0, 1, 0 }, { "inforefinfoname", 0, 1, 0 }, { "uref", 0, 1, 0 }, { "urefurl", 0, 1, 0 }, { "urefdesc", 0, 1, 0 }, { "urefreplacement", 0, 1, 0 }, { "email", 0, 1, 0 }, { "emailaddress", 0, 1, 0 }, { "emailname", 0, 1, 0 }, { "group", 0, 0, 0 }, { "float", 1, 0, 0 }, { "floattype", 0, 0, 0 }, { "floatpos", 0, 0, 0 }, { "caption", 0, 0, 0 }, { "shortcaption", 0, 0, 0 }, { "", 0, 0, 0 }, /* TABLE (docbook) */ { "", 0, 0, 0 }, /* FIGURE (docbook) */ { "", 0, 0, 0 }, /* EXAMPLE (docbook) */ { "", 1, 0, 0 }, /* SIDEBAR (docbook) */ { "printindex", 0, 0, 0 }, { "listoffloats", 0, 0, 0 }, { "anchor", 0, 1, 0 }, { "image", 0, 0, 0 }, { "inlineimage", 0, 1, 0 }, { "alttext", 0, 1, 0 }, { "", 0, 1, 0 }, /* PRIMARY (docbook) */ { "", 0, 1, 0 }, /* SECONDARY (docbook) */ { "", 0, 0, 0 }, /* INFORMALFIGURE (docbook) */ { "", 0, 0, 0 }, /* MEDIAOBJECT (docbook) */ { "", 0, 0, 0 }, /* IMAGEOBJECT (docbook) */ { "", 0, 0, 0 }, /* IMAGEDATA (docbook) */ { "", 0, 0, 0 }, /* TEXTOBJECT (docbook) */ { "", 0, 0, 0 }, /* INDEXENTRY (docbook) */ { "", 0, 0, 0 }, /* PRIMARYIE (docbook) */ { "", 0, 0, 0 }, /* SECONDARYIE (docbook) */ { "", 0, 0, 0 }, /* INDEXDIV (docbook) */ { "multitable", 0, 0, 0 }, { "", 0, 0, 0 }, /* TGROUP (docbook) */ { "columnfraction", 0, 0, 0 }, { "thead", 0, 0, 0 }, { "tbody", 0, 0, 0 }, { "entry", 0, 0, 0 }, { "row", 0, 0, 0 }, { "", 0, 0, 0 }, /* BOOKINFO (docbook) */ { "", 0, 0, 0 }, /* ABSTRACT (docbook) */ { "", 0, 0, 0 }, /* REPLACEABLE (docbook) */ { "", 0, 0, 0 }, /* ENVAR (docbook) */ { "", 0, 0, 0 }, /* COMMENT (docbook) */ { "", 0, 0, 0 }, /* FUNCTION (docbook) */ { "", 0, 0, 0 }, /* LEGALNOTICE (docbook) */ { "contents", 0, 0, 0 }, { "shortcontents", 0, 0, 0 }, { "documentlanguage", 0, 0, 0 }, { "setvalue", 0, 0, 0 }, { "clearvalue", 0, 0, 0 }, { "definition", 0, 0, 0 }, { "definitionterm", 0, 0, 0 }, { "definitionitem", 1, 0, 0 }, { "defcategory", 0, 0, 0 }, { "deffunction", 0, 0, 0 }, { "defvariable", 0, 0, 0 }, { "defparam", 0, 0, 0 }, { "defdelimiter", 0, 0, 0 }, { "deftype", 0, 0, 0 }, { "defparamtype", 0, 0, 0 }, { "defdatatype", 0, 0, 0 }, { "defclass", 0, 0, 0 }, { "defclassvar", 0, 0, 0 }, { "defoperation", 0, 0, 0 }, { "para", 0, 0, 0 } /* Must be last */ /* name / contains para / contained in para / preserve space */ }; element docbook_element_list [] = { { "book", 0, 0, 0 }, /* TEXINFO */ { "", 0, 0, 0 }, /* SETFILENAME */ { "", 0, 0, 0 }, /* TITLEINFO */ { "title", 0, 0, 0 }, /* SETTITLE */ { "", 1, 0, 0 }, /* DOCUMENTDESCRIPTION (?) */ { "", 1, 0, 0 }, /* NODE */ { "", 0, 0, 0 }, /* NODENEXT */ { "", 0, 0, 0 }, /* NODEPREV */ { "", 0, 0, 0 }, /* NODEUP */ { "chapter", 1, 0, 0 }, { "sect1", 1, 0, 0 }, /* SECTION */ { "sect2", 1, 0, 0 }, /* SUBSECTION */ { "sect3", 1, 0, 0 }, /* SUBSUBSECTION */ { "chapter", 1, 0, 0 }, /* TOP */ { "chapter", 1, 0, 0 }, /* UNNUMBERED */ { "sect1", 1, 0, 0 }, /* UNNUMBEREDSEC */ { "sect2", 1, 0, 0 }, /* UNNUMBEREDSUBSEC */ { "sect3", 1, 0, 0 }, /* UNNUMBEREDSUBSUBSEC */ { "appendix", 1, 0, 0 }, { "sect1", 1, 0, 0 }, /* APPENDIXSEC */ { "sect2", 1, 0, 0 }, /* APPENDIXSUBSEC */ { "sect3", 1, 0, 0 }, /* APPENDIXSUBSUBSEC */ { "bridgehead", 0, 0, 0 }, /* MAJORHEADING */ { "bridgehead", 0, 0, 0 }, /* CHAPHEADING */ { "bridgehead", 0, 0, 0 }, /* HEADING */ { "bridgehead", 0, 0, 0 }, /* SUBHEADING */ { "bridgehead", 0, 0, 0 }, /* SUBSUBHEADING */ { "", 0, 0, 0 }, /* TITLEPAGE */ { "", 0, 0, 0 }, /* AUTHOR */ { "", 0, 0, 0 }, /* BOOKTITLE */ { "", 0, 0, 0 }, /* BOOKSUBTITLE */ { "", 1, 0, 0 }, /* MENU */ { "", 1, 0, 0 }, /* DETAILMENU */ { "", 1, 0, 0 }, /* MENUENTRY */ { "", 0, 0, 0 }, /* MENUTITLE */ { "", 1, 0, 0 }, /* MENUCOMMENT */ { "", 0, 0, 0 }, /* MENUNODE */ { "anchor", 0, 0, 0 }, /* NODENAME */ { "acronym", 0, 1, 0 }, { "", 0, 1, 0 }, /* ACRONYMWORD */ { "", 0, 1, 0 }, /* ACRONYMDESC */ { "abbrev", 0, 1, 0 }, { "", 0, 1, 0 }, /* ABBREVWORD */ { "", 0, 1, 0 }, /* ABBREVDESC */ { "literal", 0, 1, 0 }, /* TT */ { "literal", 0, 1, 0 }, /* CODE */ { "command", 0, 1, 0 }, /* COMMAND */ { "envar", 0, 1, 0 }, /* ENV */ { "filename", 0, 1, 0 }, /* FILE */ { "option", 0, 1, 0 }, /* OPTION */ { "literal", 0, 1, 0 }, /* SAMP */ { "userinput", 0, 1, 0 }, /* KBD */ { "wordasword", 0, 1, 0 }, /* URL */ { "keycap", 0, 1, 0 }, /* KEY */ { "replaceable", 0, 1, 0 }, /* VAR */ { "", 0, 1, 0 }, /* SC */ { "firstterm", 0, 1, 0 }, /* DFN */ { "emphasis", 0, 1, 0 }, /* EMPH */ { "emphasis", 0, 1, 0 }, /* STRONG */ { "citetitle", 0, 1, 0 }, /* CITE */ { "", 0, 1, 0 }, /* NOTFIXEDWIDTH */ { "wordasword", 0, 1, 0 }, /* I */ { "emphasis", 0, 1, 0 }, /* B */ { "", 0, 1, 0 }, /* R */ { "", 0, 0, 0 }, /* EXDENT */ { "title", 0, 0, 0 }, { "", 1, 0, 0 }, /* IFINFO */ { "", 0, 0, 0 }, /* SP */ { "", 1, 0, 0 }, /* CENTER */ { "", 0, 0, 0 }, /* DIRCATEGORY */ { "blockquote", 1, 0, 0 }, /* QUOTATION */ { "screen", 0, 0, 1 }, /* EXAMPLE */ { "screen", 0, 0, 1 }, /* SMALLEXAMPLE */ { "programlisting", 0, 0, 1 }, /* LISP */ { "programlisting", 0, 0, 1 }, /* SMALLLISP */ { "", 1, 0, 0 }, /* CARTOUCHE */ { "", 1, 0, 0 }, /* COPYING */ { "screen", 0, 1, 1 }, /* FORMAT */ { "screen", 0, 1, 1 }, /* SMALLFORMAT */ { "literallayout", 0, 1, 1 }, /* DISPLAY */ { "literallayout", 0, 1, 1 }, /* SMALLDISPLAY */ { "screen", 0, 0, 1 }, /* VERBATIM */ { "footnote", 0, 1, 0 }, { "lineannotation", 0, 1, 0 }, { "tip", 1, 0, 0 }, { "note", 1, 0, 0 }, { "important", 1, 0, 0 }, { "warning", 1, 0, 0 }, { "caution", 1, 0, 0 }, { "itemizedlist", 0, 0, 0 }, /* ITEMIZE */ { "", 0, 0, 0 }, /* ITEMFUNCTION */ { "listitem", 1, 0, 0 }, /* ITEM */ { "orderedlist", 0, 0, 0 }, /* ENUMERATE */ { "variablelist", 0, 0, 0 }, /* TABLE */ { "varlistentry", 0, 0, 0 }, /* TABLEITEM */ { "term", 0, 0, 0 }, /* TABLETERM */ { "indexterm", 0, 1, 0 }, /* INDEXTERM */ { "", 0, 1, 0 }, /* MATH */ { "", 0, 1, 0 }, /* DIMENSION */ { "xref", 0, 1, 0 }, /* XREF */ { "link", 0, 1, 0 }, /* XREFNODENAME */ { "", 0, 1, 0 }, /* XREFINFONAME */ { "", 0, 1, 0 }, /* XREFPRINTEDDESC */ { "", 0, 1, 0 }, /* XREFINFOFILE */ { "", 0, 1, 0 }, /* XREFPRINTEDNAME */ { "", 0, 1, 0 }, /* INFOREF */ { "", 0, 1, 0 }, /* INFOREFNODENAME */ { "", 0, 1, 0 }, /* INFOREFREFNAME */ { "", 0, 1, 0 }, /* INFOREFINFONAME */ { "ulink", 0, 1, 0 }, /* UREF */ { "", 0, 1, 0 }, /* UREFURL */ { "", 0, 1, 0 }, /* UREFDESC */ { "", 0, 1, 0 }, /* UREFREPLACEMENT */ { "ulink", 0, 1, 0 }, /* EMAIL */ { "", 0, 1, 0 }, /* EMAILADDRESS */ { "", 0, 1, 0 }, /* EMAILNAME */ { "", 0, 0, 0 }, /* GROUP */ { "", 1, 0, 0 }, /* FLOAT */ { "", 0, 0, 0 }, /* FLOATTYPE */ { "", 0, 0, 0 }, /* FLOATPOS */ { "", 0, 0, 0 }, /* CAPTION */ { "", 0, 0, 0 }, /* SHORTCAPTION */ { "table", 0, 1, 0 }, { "figure", 0, 1, 0 }, { "example", 1, 1, 0 }, { "sidebar", 1, 0, 0 }, { "index", 0, 1, 0 }, /* PRINTINDEX */ { "", 0, 1, 0 }, /* LISTOFFLOATS */ { "", 0, 1, 0 }, /* ANCHOR */ { "", 0, 0, 0 }, /* IMAGE */ { "inlinemediaobject", 0, 1, 0 }, /* INLINEIMAGE */ { "", 0, 0, 0 }, /* IMAGEALTTEXT */ { "primary", 0, 1, 0 }, /* PRIMARY */ { "secondary", 0, 1, 0 }, { "informalfigure", 0, 0, 0 }, { "mediaobject", 0, 0, 0 }, { "imageobject", 0, 1, 0 }, { "imagedata", 0, 1, 0 }, { "textobject", 0, 1, 0 }, { "indexentry", 0, 0, 0 }, { "primaryie", 0, 0, 0 }, { "secondaryie", 0, 0, 0 }, { "indexdiv", 0, 0, 0 }, { "informaltable", 0, 0, 0 }, { "tgroup", 0, 0, 0 }, { "colspec", 0, 0, 0 }, { "thead", 0, 0, 0 }, { "tbody", 0, 0, 0 }, { "entry", 0, 0, 0 }, { "row", 0, 0, 0 }, { "bookinfo", 0, 0, 0 }, { "abstract", 1, 0, 0 }, { "replaceable", 0, 0, 0 }, { "envar", 0, 1, 0 }, { "comment", 0, 0, 0 }, { "function", 0, 1, 0 }, { "legalnotice", 1, 0, 0 }, { "", 0, 0, 0 }, /* CONTENTS (xml) */ { "", 0, 0, 0 }, /* SHORTCONTENTS (xml) */ { "", 0, 0, 0 }, /* DOCUMENT LANGUAGE (xml) */ { "", 0, 0, 0 }, /* SETVALUE (xml) */ { "", 0, 0, 0 }, /* CLEARVALUE (xml) */ { "blockquote", 1, 0, 0 }, /* DEFINITION */ { "screen", 0, 0, 1 }, /* DEFINITIONTERM */ { "", 0, 0, 0 }, /* DEFINITIONITEM (xml) */ { "", 0, 0, 0 }, /* DEFCATEGORY (xml) */ { "function", 0, 0, 0 }, /* DEFFUNCTION */ { "varname", 0, 0, 0 }, /* DEFVARIABLE */ { "varname", 0, 0, 0 }, /* DEFPARAM */ { "", 0, 0, 0 }, /* DEFDELIMITER (xml) */ { "returnvalue", 0, 0, 0 }, /* DEFTYPE */ { "type", 0, 0, 0 }, /* DEFPARAMTYPE */ { "structname", 0, 0, 0 }, /* DEFDATATYPE */ { "classname", 0, 0, 0 }, /* DEFCLASS */ { "property", 0, 0, 0 }, /* DEFCLASSVAR */ { "methodname", 0, 0, 0 }, /* DEFOPERATION */ { "para", 0, 0, 0 } /* Must be last */ /* name / contains para / contained in para / preserve space */ }; element *xml_element_list = NULL; typedef struct _replace_element { int element_to_replace; int element_containing; int element_replacing; } replace_element; /* Elements to replace - Docbook only ------------------- if `element_to_replace' have to be inserted as a child of `element_containing,' use `element_replacing' instead. A value of `-1' for element_replacing means `do not use any element.' */ replace_element replace_elements [] = { { I, TABLETERM, EMPH }, { B, TABLETERM, EMPH }, { TT, CODE, -1 }, { EXAMPLE, DISPLAY, -1 }, { CODE, DFN, -1 }, { CODE, VAR, -1 }, { EMPH, CODE, REPLACEABLE }, { VAR, VAR, -1}, { VAR, B, EMPH}, { B, CODE, ENVAR}, { CODE, I, EMPH}, { SAMP, VAR, -1 }, { FORMAT, BOOKINFO, ABSTRACT }, { QUOTATION, ABSTRACT, -1}, { LINEANNOTATION, LINEANNOTATION, -1 }, { LEGALNOTICE, ABSTRACT, -1 }, { QUOTATION, QUOTATION, -1 }, /* Formal versions of table and image elements. */ { MULTITABLE, FLOAT, FLOATTABLE }, { INFORMALFIGURE, FLOAT, FLOATFIGURE }, { CARTOUCHE, FLOAT, FLOATCARTOUCHE }, /* Unnecessary markup in @defun blocks. */ { VAR, DEFPARAM, -1 }, { CODE, DEFTYPE, -1 }, /* Add your elements to replace here */ {-1, 0, 0} }; int xml_in_menu_entry = 0; int xml_in_menu_entry_comment = 0; int xml_node_open = 0; int xml_node_level = -1; int xml_in_para = 0; int xml_just_after_element = 0; int xml_keep_space = 0; int xml_no_indent = 0; int xml_no_para = 0; char *xml_node_id = NULL; int xml_sort_index = 0; int xml_in_xref_token = 0; int xml_in_bookinfo = 0; int xml_in_book_title = 0; int xml_in_abstract = 0; /* Non-zero if we are handling an element that can appear between @item and @itemx, @deffn and @deffnx. */ int xml_dont_touch_items_defs = 0; /* We need to keep footnote state, because elements inside footnote may try to close the previous parent para. */ static int xml_in_footnote = 0; static int xml_after_table_term = 0; static int book_started = 0; static int first_section_opened = 0; static int xml_in_tableitem[256]; static int xml_in_item[256]; static int xml_table_level = 0; static int xml_in_def_item[256]; static int xml_definition_level = 0; int xml_after_def_term = 0; static int in_table_title = 0; static int in_indexentry = 0; static int in_secondary = 0; static int in_indexterm = 0; char * xml_id (char *id) { char *tem = xmalloc (strlen (id) + 1); char *p = tem; strcpy (tem, id); while (*p) { /* Check if a character is allowed in ID attributes. This list differs slightly from XML specs that it doesn't contain underscores. See http://xml.coverpages.org/sgmlsyn/sgmlsyn.htm, ``9.3 Name'' */ if (!strchr ("abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789-.", *p)) *p = '-'; p++; } p = tem; /* First character can only be a letter. */ if (!strchr ("abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ", *p)) *p = 'i'; return tem; } int xml_element (char *name) { int i; for (i=0; i<=PARA; i++) { if (strcasecmp (name, texinfoml_element_list[i].name) == 0) return i; } printf ("Error xml_element\n"); return -1; } void xml_begin_document (char *output_filename) { if (book_started) return; book_started = 1; /* Make sure this is the very first string of the output document. */ output_paragraph_offset = 0; insert_string ("\n"); if (docbook) { insert_string ("\n \n]>"); xml_element_list = docbook_element_list; } else { insert_string (""); xml_element_list = texinfoml_element_list; } if (language_code != last_language_code) { if (docbook) xml_insert_element_with_attribute (TEXINFO, START, "lang=\"%s\"", language_table[language_code].abbrev); else xml_insert_element_with_attribute (TEXINFO, START, "xml:lang=\"%s\"", language_table[language_code].abbrev); } if (!docbook) { xml_insert_element (SETFILENAME, START); insert_string (output_filename); xml_insert_element (SETFILENAME, END); } } /* */ static int element_stack[256]; static int element_stack_index = 0; static int xml_current_element (void) { return element_stack[element_stack_index-1]; } static void xml_push_current_element (int elt) { element_stack[element_stack_index++] = elt; if (element_stack_index > 200) printf ("*** stack overflow (%d - %s) ***\n", element_stack_index, xml_element_list[elt].name); } static void xml_pop_current_element (void) { element_stack_index--; if (element_stack_index < 0) printf ("*** stack underflow (%d - %d) ***\n", element_stack_index, xml_current_element()); } int xml_current_stack_index (void) { return element_stack_index; } void xml_end_current_element (void) { xml_insert_element (xml_current_element (), END); } static void xml_indent (void) { if (xml_indentation_increment > 0) { int i; if (output_paragraph[output_paragraph_offset-1] != '\n') insert ('\n'); for (i = 0; i < element_stack_index * xml_indentation_increment; i++) insert (' '); } } void xml_start_para (void) { if (xml_in_para || xml_in_footnote || !xml_element_list[xml_current_element()].contains_para) return; while (output_paragraph[output_paragraph_offset-1] == '\n') output_paragraph_offset--; xml_indent (); insert_string (""); xml_no_indent = 0; xml_in_para = 1; } void xml_end_para (void) { if (!xml_in_para || xml_in_footnote) return; while (cr_or_whitespace(output_paragraph[output_paragraph_offset-1])) output_paragraph_offset--; insert_string (""); if (xml_indentation_increment > 0) insert ('\n'); xml_in_para = 0; } void xml_end_document (void) { if (xml_node_open) { if (xml_node_level != -1) { xml_close_sections (xml_node_level); xml_node_level = -1; } xml_insert_element (NODE, END); } else xml_close_sections (xml_node_level); xml_insert_element (TEXINFO, END); if (xml_indentation_increment == 0) insert ('\n'); insert_string ("\n"); if (element_stack_index != 0) error ("Element stack index : %d\n", element_stack_index); } /* MUST be 0 or 1, not true or false values */ static int start_element_inserted = 1; /* NOTE: We use `elt' rather than `element' in the argument list of the next function, since otherwise the Solaris SUNWspro compiler barfs because `element' is a typedef declared near the beginning of this file. */ void #if defined (VA_FPRINTF) && __STDC__ xml_insert_element_with_attribute (int elt, int arg, char *format, ...) #else xml_insert_element_with_attribute (elt, arg, format, va_alist) int elt; int arg; char *format; va_dcl #endif { /* Look at the replace_elements table to see if we have to change the element */ if (xml_sort_index) return; if (docbook) { replace_element *element_list = replace_elements; while (element_list->element_to_replace >= 0) { if ( ( (arg == START) && (element_list->element_containing == xml_current_element ()) && (element_list->element_to_replace == elt) ) || ( (arg == END) && (element_list->element_containing == element_stack[element_stack_index-1-start_element_inserted]) && (element_list->element_to_replace == elt) ) ) { elt = element_list->element_replacing; break; } element_list ++; } /* Forget the element */ if (elt < 0) { if (arg == START) start_element_inserted = 0; else /* Replace the default value, for the next time */ start_element_inserted = 1; return; } } if (!book_started) return; if (!xml_dont_touch_items_defs && arg == START) { if (xml_after_table_term && elt != TABLETERM && xml_table_level && !xml_in_item[xml_table_level]) { xml_after_table_term = 0; xml_insert_element (ITEM, START); xml_in_item[xml_table_level] = 1; } else if (xml_after_def_term && elt != DEFINITIONTERM) { xml_after_def_term = 0; xml_insert_element (DEFINITIONITEM, START); xml_in_def_item[xml_definition_level] = 1; } } if (docbook && !only_macro_expansion && (in_menu || in_detailmenu)) return; if (executing_string && arg == END) switch (elt) { case TABLEITEM: xml_in_tableitem[xml_table_level] = 0; break; case ITEM: xml_in_item[xml_table_level] = 0; break; case DEFINITIONTERM: xml_in_def_item[xml_definition_level] = 0; break; } /* We are special-casing FIGURE element for docbook. It does appear in the tag stack, but not in the output. This is to make element replacement work beautifully. */ if (docbook && elt == FLOAT) { if (arg == START) xml_push_current_element (elt); else xml_pop_current_element (); return; } if (!xml_element_list[elt].name || !strlen (xml_element_list[elt].name)) { /*printf ("Warning: Inserting empty element %d\n", elt);*/ return; } if (arg == START && !xml_in_para && !xml_no_para && xml_element_list[elt].contained_in_para) xml_start_para (); if (arg == START && xml_in_para && !xml_element_list[elt].contained_in_para) xml_end_para (); if (arg == END && xml_in_para && !xml_element_list[elt].contained_in_para) xml_end_para (); if (docbook && xml_table_level && !in_table_title && !xml_in_tableitem[xml_table_level] && !xml_in_item[xml_table_level] && arg == START && elt != TABLEITEM && elt != TABLETERM && !in_indexterm && xml_current_element() == TABLE) { in_table_title = 1; xml_insert_element (TITLE, START); } if (arg == START && !xml_in_para && !xml_keep_space && !xml_element_list[elt].contained_in_para) xml_indent (); if (arg == START) xml_push_current_element (elt); else xml_pop_current_element (); /* Eat one newline before and the like. */ if (!docbook && arg == END && (xml_element_list[elt].keep_space || elt == GROUP) && output_paragraph[output_paragraph_offset-1] == '\n') output_paragraph_offset--; /* And eat whitespace before in @multitables. */ if (arg == END && elt == ENTRY) while (cr_or_whitespace(output_paragraph[output_paragraph_offset-1])) output_paragraph_offset--; /* Indent elements that can contain . */ if (arg == END && !xml_in_para && !xml_keep_space && xml_element_list[elt].contains_para) xml_indent (); /* Here are the elements we want indented. These do not contain directly. */ if (arg == END && (elt == MENUENTRY || elt == ITEMIZE || elt == ENUMERATE || elt == TABLEITEM || elt == TABLE || elt == MULTITABLE || elt == TGROUP || elt == THEAD || elt == TBODY || elt == ROW || elt == INFORMALFIGURE || (!docbook && (elt == DEFINITION || elt == DEFINITIONTERM)))) xml_indent (); insert ('<'); if (arg == END) insert ('/'); insert_string (xml_element_list[elt].name); /* printf ("%s ", xml_element_list[elt].name);*/ if (format) { char temp_string[2000]; /* xx no fixed limits */ #ifdef VA_SPRINTF va_list ap; #endif VA_START (ap, format); #ifdef VA_SPRINTF VA_SPRINTF (temp_string, format, ap); #else sprintf (temp_string, format, a1, a2, a3, a4, a5, a6, a7, a8); #endif insert (' '); insert_string (temp_string); va_end (ap); } if (arg == START && xml_node_id && elt != NODENAME) { insert_string (" id=\""); insert_string (xml_node_id); insert ('"'); free (xml_node_id); xml_node_id = NULL; } if (xml_element_list[elt].keep_space) { if (arg == START) { if (!docbook) insert_string (" xml:space=\"preserve\""); xml_keep_space++; } else xml_keep_space--; } insert ('>'); if (!xml_in_para && !xml_element_list[elt].contained_in_para && xml_element_list[elt].contains_para && xml_indentation_increment > 0) insert ('\n'); xml_just_after_element = 1; } /* See the NOTE before xml_insert_element_with_attribute, for why we use `elt' rather than `element' here. */ void xml_insert_element (int elt, int arg) { xml_insert_element_with_attribute (elt, arg, NULL); } void xml_insert_entity (char *entity_name) { int saved_escape_html = escape_html; if (!book_started) return; if (docbook && !only_macro_expansion && (in_menu || in_detailmenu)) return; if (!xml_in_para && !xml_no_para && !only_macro_expansion && xml_element_list[xml_current_element ()].contains_para && !in_fixed_width_font) xml_start_para (); escape_html = 0; add_char ('&'); escape_html = saved_escape_html; insert_string (entity_name); add_char (';'); } typedef struct _xml_section xml_section; struct _xml_section { int level; char *name; xml_section *prev; }; xml_section *last_section = NULL; void xml_begin_node (void) { first_section_opened = 1; if (xml_in_abstract) { xml_insert_element (ABSTRACT, END); xml_in_abstract = 0; } if (xml_in_bookinfo) { xml_insert_element (BOOKINFO, END); xml_in_bookinfo = 0; } if (xml_node_open && ! docbook) { if (xml_node_level != -1) { xml_close_sections (xml_node_level); xml_node_level = -1; } xml_insert_element (NODE, END); } xml_insert_element (NODE, START); xml_node_open = 1; } void xml_close_sections (int level) { if (!first_section_opened) { if (xml_in_abstract) { xml_insert_element (ABSTRACT, END); xml_in_abstract = 0; } if (xml_in_bookinfo) { xml_insert_element (BOOKINFO, END); xml_in_bookinfo = 0; } first_section_opened = 1; } while (last_section && last_section->level >= level) { xml_section *temp = last_section; xml_insert_element (xml_element(last_section->name), END); temp = last_section; last_section = last_section->prev; free (temp->name); free (temp); } } void xml_open_section (int level, char *name) { xml_section *sect = (xml_section *) xmalloc (sizeof (xml_section)); sect->level = level; sect->name = xmalloc (1 + strlen (name)); strcpy (sect->name, name); sect->prev = last_section; last_section = sect; if (xml_node_open && xml_node_level == -1) xml_node_level = level; } void xml_start_menu_entry (char *tem) { char *string; discard_until ("* "); /* The line number was already incremented in reader_loop when we saw the newline, and discard_until has now incremented again. */ line_number--; if (xml_in_menu_entry) { if (xml_in_menu_entry_comment) { xml_insert_element (MENUCOMMENT, END); xml_in_menu_entry_comment=0; } xml_insert_element (MENUENTRY, END); xml_in_menu_entry=0; } xml_insert_element (MENUENTRY, START); xml_in_menu_entry=1; xml_insert_element (MENUNODE, START); string = expansion (tem, 0); add_word (string); xml_insert_element (MENUNODE, END); free (string); /* The menu item may use macros, so expand them now. */ xml_insert_element (MENUTITLE, START); only_macro_expansion++; get_until_in_line (1, ":", &string); only_macro_expansion--; execute_string ("%s", string); /* get escaping done */ xml_insert_element (MENUTITLE, END); free (string); if (looking_at ("::")) discard_until (":"); else { /* discard the node name */ get_until_in_line (0, ".", &string); free (string); } input_text_offset++; /* discard the second colon or the period */ skip_whitespace_and_newlines(); xml_insert_element (MENUCOMMENT, START); xml_in_menu_entry_comment ++; } void xml_end_menu (void) { if (xml_in_menu_entry) { if (xml_in_menu_entry_comment) { xml_insert_element (MENUCOMMENT, END); xml_in_menu_entry_comment --; } xml_insert_element (MENUENTRY, END); xml_in_menu_entry--; } xml_insert_element (MENU, END); } static int xml_last_character; void xml_add_char (int character) { if (!book_started) return; if (docbook && !only_macro_expansion && (in_menu || in_detailmenu)) return; if (docbook && xml_table_level && !in_table_title && !xml_in_item[xml_table_level] && !xml_in_tableitem[xml_table_level] && !cr_or_whitespace (character) && !in_indexterm) { in_table_title = 1; xml_insert_element (TITLE, START); } if (!first_section_opened && !xml_in_abstract && !xml_in_book_title && !xml_no_para && character != '\r' && character != '\n' && character != ' ' && !is_in_insertion_of_type (copying)) { if (!xml_in_bookinfo) { xml_insert_element (BOOKINFO, START); xml_in_bookinfo = 1; } xml_insert_element (ABSTRACT, START); xml_in_abstract = 1; } if (!xml_sort_index && !xml_in_xref_token && !xml_dont_touch_items_defs) { if (xml_after_table_term && xml_table_level && !xml_in_item[xml_table_level]) { xml_after_table_term = 0; xml_insert_element (ITEM, START); xml_in_item[xml_table_level] = 1; } else if (xml_after_def_term) { xml_after_def_term = 0; xml_insert_element (DEFINITIONITEM, START); xml_in_def_item[xml_definition_level] = 1; } } if (xml_just_after_element && !xml_in_para && !inhibit_paragraph_indentation) { if (character == '\r' || character == '\n' || character == '\t' || character == ' ') return; xml_just_after_element = 0; } if (xml_element_list[xml_current_element()].contains_para && !xml_in_para && !only_macro_expansion && !xml_no_para && !cr_or_whitespace (character) && !in_fixed_width_font) xml_start_para (); if (xml_in_para && character == '\n' && xml_last_character == '\n' && !only_macro_expansion && !xml_no_para && xml_element_list[xml_current_element()].contains_para ) { xml_end_para (); xml_just_after_element = 1; return; } if (xml_in_menu_entry_comment && character == '\n' && xml_last_character == '\n') { xml_insert_element (MENUCOMMENT, END); xml_in_menu_entry_comment = 0; xml_insert_element (MENUENTRY, END); xml_in_menu_entry = 0; } if (xml_in_menu_entry_comment && whitespace(character) && cr_or_whitespace(xml_last_character)) return; if (character == '\n' && !xml_in_para && !inhibit_paragraph_indentation) return; xml_last_character = character; if (character == '&' && escape_html) insert_string ("&"); else if (character == '<' && escape_html) insert_string ("<"); else if (character == '\n' && !xml_keep_space) { if (!xml_in_para && xml_just_after_element && !multitable_active) return; else insert (docbook ? '\n' : ' '); } else insert (character); return; } void xml_insert_footnote (char *note) { if (!xml_in_para) xml_start_para (); xml_in_footnote = 1; xml_insert_element (FOOTNOTE, START); insert_string (""); execute_string ("%s", note); insert_string (""); xml_insert_element (FOOTNOTE, END); xml_in_footnote = 0; } /* We need to keep the quotation stack ourself, because insertion_stack loses item_function when we are closing the block, so we don't know what to close then. */ typedef struct quotation_elt { struct quotation_elt *next; char *type; } QUOTATION_ELT; static QUOTATION_ELT *quotation_stack = NULL; void xml_insert_quotation (char *type, int arg) { int quotation_started = 0; if (arg == START) { QUOTATION_ELT *new = xmalloc (sizeof (QUOTATION_ELT)); new->type = xstrdup (type); new->next = quotation_stack; quotation_stack = new; } else type = quotation_stack->type; /* Make use of special quotation styles of Docbook if we can. */ if (docbook && strlen(type)) { /* Let's assume it started. */ quotation_started = 1; if (strcasecmp (type, "tip") == 0) xml_insert_element (TIP, arg); else if (strcasecmp (type, "note") == 0) xml_insert_element (NOTE, arg); else if (strcasecmp (type, "important") == 0) xml_insert_element (IMPORTANT, arg); else if (strcasecmp (type, "warning") == 0) xml_insert_element (WARNING, arg); else if (strcasecmp (type, "caution") == 0) xml_insert_element (CAUTION, arg); else /* Didn't find a known quotation type :\ */ quotation_started = 0; } if (!quotation_started) { xml_insert_element (QUOTATION, arg); if (strlen(type) && arg == START) execute_string ("@b{%s:} ", type); } if (arg == END) { QUOTATION_ELT *temp = quotation_stack; if (temp == NULL) return; quotation_stack = quotation_stack->next; free(temp->type); free(temp); } } /* Starting generic docbook floats. Just starts elt with correct label and id attributes, and inserts title. */ void xml_begin_docbook_float (int elt) { if (current_float_used_title ()) /* in a nested float */ { xml_insert_element (elt, START); /* just insert the tag */ return; } /* OK, need the title, tag, etc. */ if (elt == CARTOUCHE) /* no labels on */ { if (strlen (current_float_id ()) == 0) xml_insert_element (elt, START); else xml_insert_element_with_attribute (elt, START, "id=\"%s\"", xml_id (current_float_id ())); } else if (strlen (current_float_id ()) == 0) xml_insert_element_with_attribute (elt, START, "label=\"\""); else xml_insert_element_with_attribute (elt, START, "id=\"%s\" label=\"%s\"", xml_id (current_float_id ()), current_float_number ()); xml_insert_element (TITLE, START); execute_string ("%s", current_float_title ()); xml_insert_element (TITLE, END); current_float_set_title_used (); /* mark this title, tag, etc used */ } /* * Lists and Tables */ void xml_begin_table (int type, char *item_function) { switch (type) { case ftable: case vtable: case table: /*if (docbook)*/ /* 05-08 */ { xml_insert_element (TABLE, START); xml_table_level ++; xml_in_tableitem[xml_table_level] = 0; xml_in_item[xml_table_level] = 0; xml_after_table_term = 0; } break; case itemize: if (!docbook) { xml_insert_element (ITEMIZE, START); xml_table_level ++; xml_in_item[xml_table_level] = 0; xml_insert_element (ITEMFUNCTION, START); if (*item_function == COMMAND_PREFIX && item_function[strlen (item_function) - 1] != '}' && command_needs_braces (item_function + 1)) execute_string ("%s{}", item_function); else execute_string ("%s", item_function); xml_insert_element (ITEMFUNCTION, END); } else { xml_insert_element_with_attribute (ITEMIZE, START, "mark=\"%s\"", (*item_function == COMMAND_PREFIX) ? &item_function[1] : item_function); xml_table_level ++; xml_in_item[xml_table_level] = 0; } break; } } void xml_end_table (int type) { switch (type) { case ftable: case vtable: case table: if (xml_in_item[xml_table_level]) { xml_insert_element (ITEM, END); xml_in_item[xml_table_level] = 0; } if (xml_in_tableitem[xml_table_level]) { xml_insert_element (TABLEITEM, END); xml_in_tableitem[xml_table_level] = 0; } xml_insert_element (TABLE, END); xml_after_table_term = 0; xml_table_level --; break; case itemize: if (xml_in_item[xml_table_level]) { xml_insert_element (ITEM, END); xml_in_item[xml_table_level] = 0; } /* gnat-style manual contains an itemized list without items! */ if (in_table_title) { xml_insert_element (TITLE, END); in_table_title = 0; } xml_insert_element (ITEMIZE, END); xml_table_level --; break; } } void xml_begin_item (void) { if (xml_in_item[xml_table_level]) xml_insert_element (ITEM, END); xml_insert_element (ITEM, START); xml_in_item[xml_table_level] = 1; } void xml_begin_table_item (void) { if (!xml_after_table_term) { if (xml_in_item[xml_table_level]) xml_insert_element (ITEM, END); if (xml_in_tableitem[xml_table_level]) xml_insert_element (TABLEITEM, END); if (in_table_title) { in_table_title = 0; xml_insert_element (TITLE, END); } xml_insert_element (TABLEITEM, START); } xml_insert_element (TABLETERM, START); xml_in_tableitem[xml_table_level] = 1; xml_in_item[xml_table_level] = 0; xml_after_table_term = 0; } void xml_continue_table_item (void) { xml_insert_element (TABLETERM, END); xml_after_table_term = 1; xml_in_item[xml_table_level] = 0; } void xml_begin_enumerate (char *enum_arg) { if (!docbook) xml_insert_element_with_attribute (ENUMERATE, START, "first=\"%s\"", enum_arg); else { if (isdigit (*enum_arg)) { int enum_val = atoi (enum_arg); /* Have to check the value, not just the first digit. */ if (enum_val == 0) xml_insert_element_with_attribute (ENUMERATE, START, "numeration=\"arabic\" role=\"0\"", NULL); else if (enum_val == 1) xml_insert_element_with_attribute (ENUMERATE, START, "numeration=\"arabic\"", NULL); else xml_insert_element_with_attribute (ENUMERATE, START, "continuation=\"continues\" numeration=\"arabic\"", NULL); } else if (isupper (*enum_arg)) { if (enum_arg[0] == 'A') xml_insert_element_with_attribute (ENUMERATE, START, "numeration=\"upperalpha\"", NULL); else xml_insert_element_with_attribute (ENUMERATE, START, "continuation=\"continues\" numeration=\"upperalpha\"", NULL); } else { if (enum_arg[0] == 'a') xml_insert_element_with_attribute (ENUMERATE, START, "numeration=\"loweralpha\"", NULL); else xml_insert_element_with_attribute (ENUMERATE, START, "continuation=\"continues\" numeration=\"loweralpha\"", NULL); } } xml_table_level ++; xml_in_item[xml_table_level] = 0; } void xml_end_enumerate (void) { if (xml_in_item[xml_table_level]) { xml_insert_element (ITEM, END); xml_in_item[xml_table_level] = 0; } xml_insert_element (ENUMERATE, END); xml_table_level --; } static void xml_insert_text_file (char *name_arg) { char *fullname = xmalloc (strlen (name_arg) + 4 + 1); FILE *image_file; strcpy (fullname, name_arg); strcat (fullname, ".txt"); image_file = fopen (fullname, "r"); if (image_file) { int ch; int save_inhibit_indentation = inhibit_paragraph_indentation; int save_filling_enabled = filling_enabled; xml_insert_element (TEXTOBJECT, START); xml_insert_element (DISPLAY, START); inhibit_paragraph_indentation = 1; filling_enabled = 0; last_char_was_newline = 0; /* Maybe we need to remove the final newline if the image file is only one line to allow in-line images. On the other hand, they could just make the file without a final newline. */ while ((ch = getc (image_file)) != EOF) add_char (ch); inhibit_paragraph_indentation = save_inhibit_indentation; filling_enabled = save_filling_enabled; xml_insert_element (DISPLAY, END); xml_insert_element (TEXTOBJECT, END); if (fclose (image_file) != 0) perror (fullname); } else warning (_("@image file `%s' unreadable: %s"), fullname, strerror (errno)); free (fullname); } /* If NAME.EXT is accessible or FORCE is nonzero, insert a docbook imagedata element for FMT. Return 1 if inserted something, 0 else. */ static int try_docbook_image (const char *name, const char *ext, const char *fmt, int force) { int used = 0; char *fullname = xmalloc (strlen (name) + 1 + strlen (ext) + 1); sprintf (fullname, "%s.%s", name, ext); if (force || access (fullname, R_OK) == 0) { xml_insert_element (IMAGEOBJECT, START); xml_insert_element_with_attribute (IMAGEDATA, START, "fileref=\"%s\" format=\"%s\"", fullname, fmt); xml_insert_element (IMAGEDATA, END); xml_insert_element (IMAGEOBJECT, END); used = 1; } free (fullname); return used; } void xml_insert_docbook_image (char *name_arg) { int found = 0; int elt = xml_in_para ? INLINEIMAGE : MEDIAOBJECT; if (is_in_insertion_of_type (floatenv)) xml_begin_docbook_float (INFORMALFIGURE); else if (!xml_in_para) xml_insert_element (INFORMALFIGURE, START); xml_no_para++; xml_insert_element (elt, START); /* A selected few from http://docbook.org/tdg/en/html/imagedata.html. */ if (try_docbook_image (name_arg, "eps", "EPS", 0)) found++; if (try_docbook_image (name_arg, "gif", "GIF", 0)) found++; if (try_docbook_image (name_arg, "jpg", "JPG", 0)) found++; if (try_docbook_image (name_arg, "jpeg", "JPEG", 0)) found++; if (try_docbook_image (name_arg, "pdf", "PDF", 0)) found++; if (try_docbook_image (name_arg, "png", "PNG", 0)) found++; if (try_docbook_image (name_arg, "svg", "SVG", 0)) found++; /* If no luck so far, just assume we'll eventually have a jpg. */ if (!found) try_docbook_image (name_arg, "jpg", "JPG", 1); xml_insert_text_file (name_arg); xml_insert_element (elt, END); xml_no_para--; if (elt == MEDIAOBJECT) xml_insert_element (INFORMALFIGURE, END); } void xml_asterisk (void) { } /* * INDEX */ /* Used to separate primary and secondary entries in an index -- we need to have real multilivel indexing support, not just string analysis. */ #define INDEX_SEP "@this string will never appear@" /* was , */ typedef struct { char *from; char *to; } XML_SYNONYM; static XML_SYNONYM **xml_synonyms = NULL; static int xml_synonyms_count = 0; void xml_insert_indexterm (char *indexterm, char *index) { /* @index commands can appear between @item and @itemx, @deffn and @deffnx. */ if (!docbook) { /* Check to see if we need to do index redirection per @synindex. */ int i; for (i = 0; i < xml_synonyms_count; i++) { if (STREQ (xml_synonyms[i]->from, index)) index = xstrdup (xml_synonyms[i]->to); } xml_dont_touch_items_defs++; xml_insert_element_with_attribute (INDEXTERM, START, "index=\"%s\"", index); in_indexterm = 1; execute_string ("%s", indexterm); xml_insert_element (INDEXTERM, END); in_indexterm = 0; xml_dont_touch_items_defs--; } else { char *primary = NULL, *secondary = NULL; if (strstr (indexterm+1, INDEX_SEP)) { primary = xmalloc (strlen (indexterm) + 1); strcpy (primary, indexterm); secondary = strstr (primary+1, INDEX_SEP); *secondary = '\0'; secondary += strlen (INDEX_SEP); } xml_insert_element_with_attribute (INDEXTERM, START, "role=\"%s\"", index); in_indexterm = 1; xml_insert_element (PRIMARY, START); if (primary) execute_string ("%s", primary); else execute_string ("%s", indexterm); xml_insert_element (PRIMARY, END); if (primary) { xml_insert_element (SECONDARY, START); execute_string ("%s", secondary); xml_insert_element (SECONDARY, END); } xml_insert_element (INDEXTERM, END); in_indexterm = 0; } } int xml_last_section_output_position = 0; static char last_division_letter = ' '; static char index_primary[2000]; /** xx no fixed limit */ static int indexdivempty = 0; static void xml_close_indexentry (void) { if (!in_indexentry) return; if (in_secondary) xml_insert_element (SECONDARYIE, END); xml_insert_element (INDEXENTRY, END); in_secondary = 0; in_indexentry = 0; } void xml_begin_index (void) { typedef struct xml_index_title { struct xml_index_title *next; char *title; } XML_INDEX_TITLE; static XML_INDEX_TITLE *xml_index_titles = NULL; if (!handling_delayed_writes) { /* We assume that we just opened a section, and so that the last output is
Title where SECTION can be CHAPTER, ... */ XML_INDEX_TITLE *new = xmalloc (sizeof (XML_INDEX_TITLE)); xml_section *temp = last_section; int l = output_paragraph_offset-xml_last_section_output_position; char *tmp = xmalloc (l+1); char *p = tmp; strncpy (tmp, (char *) output_paragraph, l); /* We remove
Title */ insert_string (xml_index_titles->title); free (xml_index_titles->title); xml_index_titles = xml_index_titles->next; } if (xml_index_divisions) { xml_insert_element (INDEXDIV, START); indexdivempty = 1; } } } void xml_end_index (void) { xml_close_indexentry (); if (xml_index_divisions) xml_insert_element (INDEXDIV, END); xml_insert_element (PRINTINDEX, END); } static void xml_index_divide (char *entry) { char c; if (strlen (entry) > (strlen (xml_element_list[CODE].name) + 2) && strncmp (entry+1, xml_element_list[CODE].name, strlen (xml_element_list[CODE].name)) == 0) c = entry[strlen (xml_element_list[CODE].name)+2]; else c = entry[0]; if (tolower (c) != last_division_letter && isalpha (c)) { last_division_letter = tolower (c); xml_close_indexentry (); if (!indexdivempty) { xml_insert_element (INDEXDIV, END); xml_insert_element (INDEXDIV, START); } xml_insert_element (TITLE, START); insert (toupper (c)); xml_insert_element (TITLE, END); } } void xml_insert_indexentry (char *entry, char *node) { char *primary = NULL, *secondary; if (xml_index_divisions) xml_index_divide (entry); indexdivempty = 0; if (strstr (entry+1, INDEX_SEP)) { primary = xmalloc (strlen (entry) + 1); strcpy (primary, entry); secondary = strstr (primary+1, INDEX_SEP); *secondary = '\0'; secondary += strlen (INDEX_SEP); if (in_secondary && strcmp (primary, index_primary) == 0) { xml_insert_element (SECONDARYIE, END); xml_insert_element (SECONDARYIE, START); execute_string ("%s", secondary); } else { xml_close_indexentry (); xml_insert_element (INDEXENTRY, START); in_indexentry = 1; xml_insert_element (PRIMARYIE, START); execute_string ("%s", primary); xml_insert_element (PRIMARYIE, END); xml_insert_element (SECONDARYIE, START); execute_string ("%s", secondary); in_secondary = 1; } } else { xml_close_indexentry (); xml_insert_element (INDEXENTRY, START); in_indexentry = 1; xml_insert_element (PRIMARYIE, START); execute_string ("%s", entry); } add_word (", "); /* Don't link to @unnumbered sections directly. We are disabling warnings temporarily, otherwise these xrefs will cause bogus warnings about missing punctuation. */ { extern int print_warnings; int save_print_warnings = print_warnings; print_warnings = 0; execute_string ("%cxref{%s}", COMMAND_PREFIX, xstrdup (node)); print_warnings = save_print_warnings; } if (primary) { strcpy (index_primary, primary); /* xml_insert_element (SECONDARYIE, END);*/ /* *(secondary-1) = ',';*/ /* necessary ? */ free (primary); } else xml_insert_element (PRIMARYIE, END); /* xml_insert_element (INDEXENTRY, END); */ } void xml_synindex (char *from, char *to) { int i, slot; slot = -1; for (i = 0; i < xml_synonyms_count; i++) if (!xml_synonyms[i]) { slot = i; break; } if (slot < 0) { slot = xml_synonyms_count; xml_synonyms_count++; xml_synonyms = (XML_SYNONYM **) xrealloc (xml_synonyms, (xml_synonyms_count + 1) * sizeof (XML_SYNONYM *)); } xml_synonyms[slot] = xmalloc (sizeof (XML_SYNONYM)); xml_synonyms[slot]->from = xstrdup (from); xml_synonyms[slot]->to = xstrdup (to); } /* * MULTITABLE */ static int multitable_columns_count; static int *multitable_column_widths; void xml_begin_multitable (int ncolumns, int *column_widths) { int i; if (docbook) { if (is_in_insertion_of_type (floatenv)) xml_begin_docbook_float (MULTITABLE); else xml_insert_element (MULTITABLE, START); multitable_columns_count = ncolumns; multitable_column_widths = xmalloc (sizeof (int) * ncolumns); memcpy (multitable_column_widths, column_widths, sizeof (int) * ncolumns); xml_no_para = 1; } else { xml_insert_element (MULTITABLE, START); for (i=0; i