code:
<!-- $Id$
  Document Type Definition for Texinfo XML output (the '-'-xml option).

  Copyright 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010,
  2011, 2012, 2013, 2014, 2015, 2016 Free Software Foundation, Inc.

  Copying and distribution of this file, with or without modification,
  are permitted in any medium without royalty provided the copyright
  notice and this notice are preserved.

  As soon as this file is nontrivially modified, update
  TEXINFO_DTD_VERSION in configure.ac (if not already done).
  See comments there for explanation.

  Email bug-texinfo@gnu.org with any discussion.
  (Original author: Philippe Martin.)
-->

<!-- * ENTITIES * -->

<!-- Meta-information -->
<!-- copying | titlepage could be there too -->
<!ENTITY % metainformation "setfilename | settitle | dircategory | direntry
                            | hyphenation
                            | documentdescription
                            | shorttitlepage">
<!ENTITY % variable.cmds "set | clear">

<!-- Unique options -->
<!ENTITY % unique.option.cmds "novalidate | setcontentsaftertitlepage
   | setshortcontentsaftertitlepage | documentencoding
   | everyheadingmarks | everyfootingmarks | evenheadingmarks | oddheadingmarks
   | evenfootingmarks | oddfootingmarks | fonttextsize | pagesizes
   | setchapternewpage | footnotestyle | finalout

   | allowcodebreaks | exampleindent | afourpaper
   | afivepaper | afourlatex | afourwide | headings
   | everyheading | everyfooting | evenheading | evenfooting | oddheading
   | oddfooting | smallbook | cropmarks">

<!-- Global options in the main text -->
<!ENTITY % global.option.cmds "synindex | syncodeindex
  | defindex | defcodeindex | definfoenclose | alias">

<!-- Options -->
<!ENTITY % multiple.option.cmds "frenchspacing | documentlanguage
    | %variable.cmds; | kbdinputstyle | paragraphindent
    | firstparagraphindent | urefbreakstyle | xrefautomaticsectiontitle
    | deftypefnnewline
    | codequoteundirected | codequotebacktick | raisesections
    | lowersections | clickstyle">

<!ENTITY % option.cmds "%unique.option.cmds; | %global.option.cmds;
               | %multiple.option.cmds;">

<!-- ToC -->
<!ENTITY % toc "contents | shortcontents | summarycontents">

<!-- Title page -->
<!ENTITY % titlepage.cmds "author | title | subtitle">

<!-- index entry commands -->
<!ENTITY % indexentry.cmds "cindex | findex | kindex | pindex | tindex
  | vindex | indexcommand">

<!-- API definition commands -->
<!ENTITY % def.cmds "deffn | defvr | deftypefn | deftypeop | deftypevr
      | defcv | deftypecv | defop | deftp | defun | defmac
      | defspec | defvar | defopt | deftypefun | deftypevar
      | defivar | deftypeivar | defmethod | deftypemethod">

<!ENTITY % raw.cmds "html | tex | docbook | xml | macro | rmacro | ignore">

<!-- Commands that appear everywhere, both with block and in paragraphs -->
<!-- include is in general absent, since it is replaced, but it is
     present if the file was not found -->
<!ENTITY % ubiquitous.cmds "sp | anchor | indent | noindent | %raw.cmds;
                 | %option.cmds; | errormsg | unmacro | include
                 | %indexentry.cmds; | refill | quote-arg | allow-recursion">

<!-- Block -->
<!ENTITY % block "menu | para | pre | quotation | smallquotation
                  | example | smallexample | lisp | smalllisp
                  | cartouche | float | format | smallformat
                  | display | smalldisplay | copying | titlepage
                  | raggedright | flushleft | flushright
                  | itemize | enumerate | titlefont | center | group
                  | table | vtable | ftable | multitable | definition
                  | image
                  | %def.cmds;
                  | %ubiquitous.cmds;
                  | verbatim | verbatiminclude | insertcopying | page | need
                  | vskip
                  | listoffloats">

<!-- API definition line -->
<!ENTITY % definition.args "defcategory | deffunction | defvariable | defparam
                          | defdelimiter | deftype | defparamtype | defdatatype
                          | defclass | defclassvar | defoperation">

<!-- Headings -->
<!ENTITY % heading.cmds "majorheading | chapheading | heading | subheading
                     | subsubheading">

<!-- Language codes -->
<!ENTITY % languagecodes "aa|ab|af|am|ar|as|ay|az|ba|be|bg|bh|bi|bn|bo|br|ca|co|cs|cy|da|de|dz|el|en|eo|es|et|eu|fa|fi|fj|fo|fr|fy|ga|gd|gl|gn|gu|ha|he|hi|hr|hu|hy|ia|id|ie|ik|is|it|iu|ja|jw|ka|kk|kl|km|kn|ko|ks|ku|ky|la|ln|lo|lt|lv|mg|mi|mk|ml|mn|mo|mr|ms|mt|my|na|ne|nl|no|oc|om|or|pa|pl|ps|pt|qu|rm|rn|ro|ru|rw|sa|sd|sg|sh|si|sk|sl|sm|sn|so|sq|sr|ss|st|su|sv|sw|ta|te|tg|th|ti|tk|tl|tn|to|tr|ts|tt|tw|ug|uk|ur|uz|vi|vo|wo|xh|yi|yo|za|zh|zu">

<!-- Sectioning -->
<!ENTITY % section.level1 "top | part | chapter | unnumbered | centerchap | appendix">

<!ENTITY % section.level2 "section | unnumberedsec | appendixsec">

<!ENTITY % section.level3 "subsection | unnumberedsubsec | appendixsubsec">

<!ENTITY % section.level4 "subsubsection | unnumberedsubsubsec
                           | appendixsubsubsec">

<!ENTITY % section.all "%section.level1; | %section.level2; | %section.level3;
                        | %section.level4;">

<!-- toplevel content, not in copying nor footnote -->
<!ENTITY % main.content "%block; | %toc; | node | %heading.cmds;
                         | printindex">

<!ENTITY % section.level0.content "(%main.content;
                                   | %section.level1;
                                   | %section.level2;
                                   | %section.level3;
                                   | %section.level4;)*">

<!ENTITY % section.level1.content "(%main.content;
                                   | %section.level2;
                                   | %section.level3;
                                   | %section.level4;)*">

<!ENTITY % section.level2.content "(%main.content;
                                   | %section.level3;
                                   | %section.level4;)*">

<!ENTITY % section.level3.content "(%main.content;
                                   | %section.level4;)*">

<!ENTITY % section.level4.content "(%main.content;)*">

<!-- Inline -->
<!ENTITY % Inline.emphasize "strong | emph">
<!ENTITY % Inline.fonts "b | i | r | sansserif | slanted | t
                         | sc">
<!ENTITY % Inline.footnote "footnote">
<!ENTITY % Inline.markup "code | command | env | file | option | samp | verb
                          | dfn | cite | key | kbd | var | acronym | abbr
                          | indicateurl | w | asis | sub | sup ">
<!ENTITY % Inline.math "math | dmn">
<!ENTITY % Inline.reference "xref | ref | pxref | inforef | email | uref | url">
<!ENTITY % Inline.misc "click | clicksequence | logo | punct | spacecmd | today
                        | linebreak | accent | dotless | ctrl | inlineraw
                        | inlinefmt | inlinefmtifelse | inlineifclear
                        | inlineifset | infoenclose | noeos | formfeed ">

<!-- on lines -->
<!ENTITY % Inline.linetext "%Inline.emphasize; | %Inline.misc; | %Inline.fonts;
          | %Inline.markup; | %Inline.math; | %Inline.reference;
          | %Inline.footnote;" >
<!ENTITY % Inline.line "%Inline.linetext; | image">
<!ENTITY % Inline.fullline "%Inline.line; | titlefont | anchor">

<!-- in paragraphs -->
<!ENTITY % Inline.phrase
           "%Inline.line; | %ubiquitous.cmds;">

<!-- in raw (everything except sectioning commands) -->
<!ENTITY % Raw.content "#PCDATA | %titlepage.cmds; | %block; | %heading.cmds;
           | %Inline.linetext; | exdent | %toc; | printindex
           | %metainformation;">

<!-- arguments/attribute values. Many are missing -->
<!ENTITY % onoff "on|off">
<!ENTITY % spacetype "spc|tab|nl">
<!ENTITY % topbottom "top|bottom">
<!ENTITY % zeroone "0|1">

<!-- ubiquitous attribute -->
<!ENTITY % spacesattr
  "spaces CDATA #IMPLIED">
<!ENTITY % lineattr
  "line CDATA #IMPLIED">
<!ENTITY % bracketedattr
  "bracketed (%onoff;) #IMPLIED">
<!-- block commands that have spaces also have endspaces -->
<!-- this is also used for commands without arguments
     when they have a @comment on their line -->
<!ENTITY % spacesblockattr
          "%spacesattr;
           endspaces CDATA #IMPLIED">

<!-- ELEMENTS -->

<!-- TOP Level Element -->
<!ELEMENT texinfo (filename?, preamble?, (%metainformation;
                    | %section.all; | %main.content;)*, bye?)>
<!ATTLIST texinfo xml:lang (%languagecodes;) 'en'>

<!-- meta-information -->
<!ELEMENT filename EMPTY>
<!ATTLIST filename
          file   CDATA #IMPLIED>
<!ELEMENT setfilename (#PCDATA  | %Inline.line;)*>
<!ATTLIST setfilename
          %spacesattr;
          file   CDATA #IMPLIED>
<!ELEMENT settitle        (#PCDATA | %Inline.line;)*>
<!ATTLIST settitle
          %spacesattr;>
<!ELEMENT shorttitlepage  (#PCDATA | %Inline.line;)*>
<!ATTLIST shorttitlepage
          %spacesattr;>
<!ELEMENT dircategory     (#PCDATA | %Inline.line;)*>
<!ATTLIST dircategory
          %spacesattr;>

<!ELEMENT set    (#PCDATA)>
<!ATTLIST set
          %lineattr;
          name CDATA #REQUIRED>
<!ELEMENT clear  EMPTY>
<!ATTLIST clear
          %lineattr;
          name CDATA #REQUIRED>
<!ELEMENT unmacro  EMPTY>
<!ATTLIST unmacro
          %lineattr;
          name CDATA #REQUIRED>
<!ELEMENT definfoenclose EMPTY>
<!ATTLIST definfoenclose
          %lineattr;
          command  NMTOKEN #REQUIRED
          open     CDATA   #IMPLIED
          close    CDATA   #IMPLIED>
<!ELEMENT alias          EMPTY>
<!ATTLIST alias
          %lineattr;
          new       NMTOKEN #REQUIRED
          existing  NMTOKEN #REQUIRED>
<!ELEMENT clickstyle  (#PCDATA)>
<!ATTLIST clickstyle
          %lineattr;
          command  NMTOKEN #REQUIRED>

<!-- preamble -->
<!ELEMENT preamble (#PCDATA)>

<!-- ToC -->
<!ELEMENT contents      EMPTY>
<!ATTLIST contents
          %lineattr;>
<!ELEMENT shortcontents EMPTY>
<!ATTLIST shortcontents
          %lineattr;>
<!ELEMENT summarycontents EMPTY>
<!ATTLIST summarycontents
          %lineattr;>

<!-- Global unique options -->
<!ELEMENT novalidate EMPTY>
<!ATTLIST novalidate
          %lineattr;>
<!ELEMENT setcontentsaftertitlepage EMPTY>
<!ATTLIST setcontentsaftertitlepage
          %lineattr;>
<!ELEMENT setshortcontentsaftertitlepage EMPTY>
<!ATTLIST setshortcontentsaftertitlepage
          %lineattr;>
<!ELEMENT documentencoding (#PCDATA)>
<!ATTLIST documentencoding
          %spacesattr;
          encoding CDATA #REQUIRED>
<!ELEMENT everyheadingmarks EMPTY>
<!ATTLIST everyheadingmarks
          %lineattr;
          value (%topbottom;) #REQUIRED>
<!ELEMENT everyfootingmarks EMPTY>
<!ATTLIST everyfootingmarks
          %lineattr;
          value (%topbottom;) #REQUIRED>
<!ELEMENT evenheadingmarks EMPTY>
<!ATTLIST evenheadingmarks
          %lineattr;
          value (%topbottom;) #REQUIRED>
<!ELEMENT oddheadingmarks EMPTY>
<!ATTLIST oddheadingmarks
          %lineattr;
          value (%topbottom;) #REQUIRED>
<!ELEMENT evenfootingmarks EMPTY>
<!ATTLIST evenfootingmarks
          %lineattr;
          value (%topbottom;) #REQUIRED>
<!ELEMENT oddfootingmarks EMPTY>
<!ATTLIST oddfootingmarks
          %lineattr;
          value (%topbottom;) #REQUIRED>
<!-- "10|11" -->
<!ELEMENT fonttextsize  EMPTY>
<!ATTLIST fonttextsize
          %lineattr;
          value CDATA #REQUIRED>
<!ELEMENT pagesizes (#PCDATA)>
<!ATTLIST pagesizes
          %spacesattr;>
<!ELEMENT setchapternewpage  EMPTY>
<!-- "off|on|odd" -->
<!ATTLIST setchapternewpage
          %lineattr;
          value CDATA #REQUIRED>
<!ELEMENT footnotestyle      EMPTY>
<!-- "end|separate" -->
<!ATTLIST footnotestyle
          %lineattr;
          value CDATA #REQUIRED>
<!ELEMENT allowcodebreaks    EMPTY>
<!-- "false|true" -->
<!ATTLIST allowcodebreaks
          %lineattr;
          value CDATA #REQUIRED>
<!ELEMENT exampleindent      EMPTY>
<!ATTLIST exampleindent
          %lineattr;
          value CDATA #REQUIRED>
<!ELEMENT afourpaper      EMPTY>
<!ATTLIST afourpaper
          %lineattr;>
<!ELEMENT afivepaper      EMPTY>
<!ATTLIST afivepaper
          %lineattr;>
<!ELEMENT afourlatex      EMPTY>
<!ATTLIST afourlatex
          %lineattr;>
<!ELEMENT afourwide       EMPTY>
<!ATTLIST afourwide
          %lineattr;>
<!ELEMENT finalout        EMPTY>
<!ATTLIST finalout
          %lineattr;>
<!ELEMENT headings        EMPTY>
<!-- "off|on|single|double|singleafter|doubleafter" -->
<!ATTLIST headings
          %lineattr;
          value CDATA #REQUIRED>
<!ELEMENT everyheading (#PCDATA)>
<!ELEMENT everyfooting (#PCDATA)>
<!ELEMENT evenheading (#PCDATA)>
<!ELEMENT evenfooting (#PCDATA)>
<!ELEMENT oddheading (#PCDATA)>
<!ELEMENT oddfooting (#PCDATA)>
<!ELEMENT vskip (#PCDATA)>
<!ELEMENT smallbook       EMPTY>
<!ATTLIST smallbook
          %lineattr;>
<!ELEMENT cropmarks       EMPTY>
<!ATTLIST cropmarks
          %lineattr;>

<!-- Global options -->
<!ELEMENT documentlanguage (#PCDATA)>
<!ATTLIST documentlanguage
          %spacesattr;
          xml:lang (%languagecodes;) 'en'>
<!ELEMENT frenchspacing (#PCDATA)> <!-- must be on or off -->
<!ATTLIST frenchspacing
          %lineattr;
          value (%onoff;) 'off'>
<!ELEMENT kbdinputstyle   EMPTY>
<!-- "code|example|distinct" -->
<!ATTLIST kbdinputstyle
          %lineattr;
          value CDATA #REQUIRED>
<!ELEMENT paragraphindent EMPTY>
<!ATTLIST paragraphindent
          %lineattr;
          value CDATA #REQUIRED>
<!ELEMENT firstparagraphindent EMPTY>
<!ATTLIST firstparagraphindent
          %lineattr;
          value CDATA #REQUIRED>
<!ELEMENT urefbreakstyle  EMPTY>
<!-- "after|before|none" -->
<!ATTLIST urefbreakstyle
          %lineattr;
          value CDATA #REQUIRED>
<!ELEMENT xrefautomaticsectiontitle EMPTY>
<!ATTLIST xrefautomaticsectiontitle
          %lineattr;
          value (%onoff;) #REQUIRED>
<!ELEMENT deftypefnnewline EMPTY>
<!ATTLIST deftypefnnewline
          %lineattr;
          value (%onoff;) #REQUIRED>
<!ELEMENT codequoteundirected EMPTY>
<!ATTLIST codequoteundirected
          %lineattr;
          value (%onoff;) #REQUIRED>
<!ELEMENT codequotebacktick EMPTY>
<!ATTLIST codequotebacktick
          %lineattr;
          value (%onoff;) #REQUIRED>
<!ELEMENT raisesections   EMPTY>
<!ATTLIST raisesections
          %lineattr;>
<!ELEMENT lowersections   EMPTY>
<!ATTLIST lowersections
          %lineattr;>

<!-- Titlepage and copying -->
<!ELEMENT copying    (%block; | %heading.cmds;)*>
<!ATTLIST copying
          %spacesblockattr;>
<!ELEMENT insertcopying EMPTY>

<!ELEMENT titlepage  (%titlepage.cmds; | %block; | %heading.cmds;)*>
<!ATTLIST titlepage
          %spacesblockattr;>
<!ELEMENT author     (#PCDATA | %Inline.line;)*>
<!ATTLIST author
          %spacesattr;>
<!ELEMENT title      (#PCDATA | %Inline.line;)*>
<!ATTLIST title
          %spacesattr;>
<!ELEMENT subtitle   (#PCDATA | %Inline.line;)*>
<!ATTLIST subtitle
          %spacesattr;>

<!-- Formatting -->
<!ELEMENT sp EMPTY>
<!ATTLIST sp
          %lineattr;
          value CDATA #IMPLIED>
<!ELEMENT page EMPTY>
<!ATTLIST page
          %lineattr;>
<!ELEMENT need EMPTY>
<!ATTLIST need
          %lineattr;
          value CDATA #REQUIRED>
<!ELEMENT indent   EMPTY>
<!ELEMENT noindent EMPTY>

<!-- emacs-page
<!ELEMENT node (nodename, nodenext?, nodeprev?, nodeup?,
                (%section.all; | %main.content;)*) >
     Nodes -->
<!ELEMENT node (nodename, nodenext?, nodeprev?, nodeup?)>
<!ATTLIST node
          %spacesattr;
          name CDATA #IMPLIED>

<!ELEMENT nodename (#PCDATA | %Inline.line;)*>
<!ATTLIST nodename
          trailingspaces CDATA #IMPLIED>
<!ELEMENT nodenext (#PCDATA | %Inline.line;)*>
<!ATTLIST nodenext
          %spacesattr;
          trailingspaces CDATA #IMPLIED
          automatic (%onoff;) 'off'>
<!ELEMENT nodeprev (#PCDATA | %Inline.line;)*>
<!ATTLIST nodeprev
          %spacesattr;
          trailingspaces CDATA #IMPLIED
          automatic (%onoff;) 'off'>
<!ELEMENT nodeup   (#PCDATA | %Inline.line;)*>
<!ATTLIST nodeup
          %spacesattr;
          trailingspaces CDATA #IMPLIED
          automatic (%onoff;) 'off'>

<!ENTITY % sectionsattr
  "%spacesattr;
   originalcommand CDATA #IMPLIED">
<!-- Sectioning -->
<!ELEMENT top           (sectiontitle?, (%section.level0.content;))>
<!ATTLIST top
          %sectionsattr;>
<!ELEMENT part          (sectiontitle?, (%section.level0.content;))>
<!ATTLIST part
          %sectionsattr;>

<!ELEMENT chapter       (sectiontitle?, (%section.level1.content;))>
<!ATTLIST chapter
          %sectionsattr;>
<!ELEMENT section       (sectiontitle?, (%section.level2.content;))>
<!ATTLIST section
          %sectionsattr;>
<!ELEMENT subsection    (sectiontitle?, (%section.level3.content;))>
<!ATTLIST subsection
          %sectionsattr;>
<!ELEMENT subsubsection (sectiontitle?, (%section.level4.content;))>
<!ATTLIST subsubsection
          %sectionsattr;>

<!ELEMENT unnumbered          (sectiontitle?, (%section.level1.content;))>
<!ATTLIST unnumbered
          %sectionsattr;>
<!ELEMENT unnumberedsec       (sectiontitle?, (%section.level2.content;))>
<!ATTLIST unnumberedsec
          %sectionsattr;>
<!ELEMENT unnumberedsubsec    (sectiontitle?, (%section.level3.content;))>
<!ATTLIST unnumberedsubsec
          %sectionsattr;>
<!ELEMENT unnumberedsubsubsec (sectiontitle?, (%section.level4.content;))>
<!ATTLIST unnumberedsubsubsec
          %sectionsattr;>
<!ELEMENT centerchap          (sectiontitle?, (%section.level1.content;))>
<!ATTLIST centerchap
          %sectionsattr;>

<!ELEMENT appendix          (sectiontitle?, (%section.level1.content;))>
<!ATTLIST appendix
          %sectionsattr;>
<!ELEMENT appendixsec       (sectiontitle?, (%section.level2.content;))>
<!ATTLIST appendixsec
          %sectionsattr;>
<!ELEMENT appendixsubsec    (sectiontitle?, (%section.level3.content;))>
<!ATTLIST appendixsubsec
          %sectionsattr;>
<!ELEMENT appendixsubsubsec (sectiontitle?, (%section.level4.content;))>
<!ATTLIST appendixsubsubsec
          %sectionsattr;>

<!-- Headings and titles -->
<!ELEMENT majorheading  (#PCDATA | %Inline.line;)*>
<!ATTLIST majorheading
          %spacesattr;>
<!ELEMENT chapheading   (#PCDATA | %Inline.line;)*>
<!ATTLIST chapheading
          %spacesattr;>
<!ELEMENT heading       (#PCDATA | %Inline.line;)*>
<!ATTLIST heading
          %spacesattr;>
<!ELEMENT subheading    (#PCDATA | %Inline.line;)*>
<!ATTLIST subheading
          %spacesattr;>
<!ELEMENT subsubheading (#PCDATA | %Inline.line;)*>
<!ATTLIST subsubheading
          %spacesattr;>
<!ELEMENT sectiontitle  (#PCDATA | %Inline.line;)*>

<!-- emacs-page
     Block elements -->

<!ELEMENT quotation    (quotationtype?, (%block; | exdent | author)*)>
<!ATTLIST quotation
          %spacesblockattr;>
<!ELEMENT smallquotation    (quotationtype?, (%block; | exdent | author)*)>
<!ATTLIST smallquotation
          %spacesblockattr;>
<!ELEMENT quotationtype (#PCDATA | %Inline.line;)*>

<!ELEMENT documentdescription (%block;)*>
<!ATTLIST documentdescription
          %spacesblockattr;>
<!ELEMENT example      (%block; | exdent)*>
<!ATTLIST example
          %spacesblockattr;>
<!ELEMENT smallexample (%block; | exdent)*>
<!ATTLIST smallexample
          %spacesblockattr;>
<!ELEMENT lisp         (%block; | exdent)*>
<!ATTLIST lisp
          %spacesblockattr;>
<!ELEMENT smalllisp    (%block; | exdent)*>
<!ATTLIST smalllisp
          %spacesblockattr;>
<!ELEMENT cartouche    (%block; | exdent)*>
<!ATTLIST cartouche
          %spacesblockattr;>
<!ELEMENT format       (%block; | exdent)*>
<!ATTLIST format
          %spacesblockattr;>
<!ELEMENT smallformat  (%block; | exdent)*>
<!ATTLIST smallformat
          %spacesblockattr;>
<!ELEMENT display      (%block; | exdent)*>
<!ATTLIST display
          %spacesblockattr;>
<!ELEMENT smalldisplay (%block; | exdent)*>
<!ATTLIST smalldisplay
          %spacesblockattr;>
<!ELEMENT group        (%block; | exdent)*>
<!ATTLIST group
          %spacesblockattr;>
<!ELEMENT flushleft    (%block; | exdent)*>
<!ATTLIST flushleft
          %spacesblockattr;>
<!ELEMENT flushright   (%block; | exdent)*>
<!ATTLIST flushright
          %spacesblockattr;>
<!ELEMENT raggedright  (%block; | exdent)*>
<!ATTLIST raggedright
          %spacesblockattr;>

<!ELEMENT center       (#PCDATA | %Inline.fullline;)*>
<!ATTLIST center
          %spacesattr;>

<!ELEMENT image        (imagefile, imagewidth?, imageheight?, alttext?,
                        imageextension?)>
<!ATTLIST image
          %spacesattr;
          where      CDATA #IMPLIED>
<!ELEMENT imagefile       (#PCDATA | %Inline.line;)*>
<!ELEMENT imagewidth      (#PCDATA)>
<!ATTLIST imagewidth
          %spacesattr;>
<!ELEMENT imageheight     (#PCDATA)>
<!ATTLIST imageheight
          %spacesattr;>
<!ELEMENT alttext         (#PCDATA | %Inline.line;)*>
<!ATTLIST alttext
          %spacesattr;>
<!ELEMENT imageextension  (#PCDATA)>
<!ATTLIST imageextension
          %spacesattr;>

<!-- Whitespace in these elements are always preserved -->
<!ELEMENT verbatim     (#PCDATA)>
<!ATTLIST verbatim
          %spacesattr;
          xml:space (preserve) #FIXED 'preserve'>

<!-- author is there because it may happen in a quotation para -->
<!ELEMENT para         (#PCDATA | %Inline.phrase; | author)*>
<!ATTLIST para
          role CDATA #IMPLIED>
<!ELEMENT pre          (#PCDATA | %Inline.phrase; | author)*>
<!ATTLIST pre          xml:space (preserve) #FIXED 'preserve'>

<!ELEMENT menu (menuentry | detailmenu | menucomment)*>
<!ATTLIST menu
          %spacesblockattr;>
<!ELEMENT detailmenu (menuentry | menucomment)*>
<!ATTLIST detailmenu
          %spacesblockattr;>
<!ELEMENT direntry (menuentry | menucomment)*>
<!ATTLIST direntry
          %spacesblockattr;>
<!ELEMENT menuentry (menutitle?, menunode?, menudescription?)>
<!ATTLIST menuentry
          leadingtext CDATA #REQUIRED>
<!ELEMENT menunode (#PCDATA | %Inline.line;)*>
<!ATTLIST menunode
          separator CDATA #IMPLIED>
<!ELEMENT menutitle (#PCDATA | %Inline.line;)*>
<!ATTLIST menutitle
          separator CDATA #IMPLIED>
<!ELEMENT menudescription (%block;)*>
<!ELEMENT menucomment (%block;)*>

<!-- Raw formats -->
<!ELEMENT docbook (%Raw.content;)*>
<!ATTLIST docbook
          %spacesblockattr;>
<!ELEMENT html (%Raw.content;)*>
<!ATTLIST html
          %spacesblockattr;>
<!ELEMENT tex (%Raw.content;)*>
<!ATTLIST tex
          %spacesblockattr;>
<!-- this may happen if xml is not expanded -->
<!ELEMENT xml (%Raw.content;)*>
<!ATTLIST xml
          %spacesblockattr;>

<!-- formalarg only before PCDATA, but mandating it seems not possible -->
<!-- same issue for nesting macros -->
<!ELEMENT macro (#PCDATA | formalarg | macro | rmacro)*>
<!ATTLIST macro
          name CDATA #REQUIRED
          line CDATA #REQUIRED>
<!ELEMENT rmacro (#PCDATA | formalarg | macro | rmacro)*>
<!ATTLIST rmacro
          name CDATA #REQUIRED
          line CDATA #REQUIRED>

<!ELEMENT formalarg (#PCDATA)>

<!ELEMENT ignore (#PCDATA)>

<!-- Negative indentation in blocks -->
<!ELEMENT exdent       (#PCDATA | %Inline.fullline;)*>
<!ATTLIST exdent
          %spacesattr;>

<!ELEMENT verbatiminclude (#PCDATA)>
<!ATTLIST verbatiminclude
          %spacesattr;
          file CDATA #REQUIRED>

<!ELEMENT include (#PCDATA)>
<!ATTLIST include
          %spacesattr;>

<!-- Floating displays -->
<!ELEMENT float (floattype?, floatname?, (%block;)*,
                (caption | shortcaption)*)>
<!ATTLIST float
          %spacesblockattr;
          number CDATA #IMPLIED
          name CDATA #IMPLIED
          type CDATA #IMPLIED>
<!ELEMENT floattype (#PCDATA | %Inline.line;)*>
<!ELEMENT floatname (#PCDATA | %Inline.line;)*>
<!ATTLIST floatname
          %spacesattr;>
<!ELEMENT caption (#PCDATA | %block;)*>
<!ATTLIST caption
          %spacesattr;>
<!ELEMENT shortcaption (#PCDATA | %Inline.phrase; | para)*>
<!ELEMENT listoffloats (#PCDATA | %Inline.line;)*>
<!ATTLIST listoffloats
          %spacesattr;
          type CDATA #IMPLIED>

<!-- Lists -->
<!ELEMENT itemize (itemprepend?, beforefirstitem?,
                   (listitem | %indexentry.cmds;)*)>
<!ATTLIST itemize
          %spacesblockattr;
          commandarg CDATA #IMPLIED>
<!ELEMENT enumerate (enumeratefirst?, beforefirstitem?,
                     (listitem | %indexentry.cmds;)*)>
<!ATTLIST enumerate
          %spacesblockattr;
          first CDATA #IMPLIED>
<!ELEMENT enumeratefirst (#PCDATA)>

<!ELEMENT listitem (prepend?, (%block;)*)>
<!ATTLIST listitem
          %spacesattr;>
<!ELEMENT prepend (#PCDATA | %Inline.line;)*>

<!ELEMENT itemprepend (#PCDATA | %Inline.line; | formattingcommand)*>
<!ELEMENT formattingcommand EMPTY>
<!ATTLIST formattingcommand
          command CDATA #REQUIRED>
<!ELEMENT beforefirstitem (%block;)*>

<!-- Tables -->
<!ELEMENT table (beforefirstitem?, (tableentry | %indexentry.cmds;)+)>

<!ENTITY % blocktablearg
         "%spacesblockattr;
          commandarg CDATA #IMPLIED
          begin CDATA #IMPLIED
          end CDATA #IMPLIED">

<!-- begin and end are for definfoenclose command as table argument -->
<!ATTLIST table
          %blocktablearg;>
<!ELEMENT vtable (beforefirstitem?, (tableentry | %indexentry.cmds;)+)>
<!ATTLIST vtable
          %blocktablearg;>
<!ELEMENT ftable (beforefirstitem?, (tableentry | %indexentry.cmds;)+)>
<!ATTLIST ftable
          %blocktablearg;>
<!ELEMENT tableentry (tableterm, tableitem?)>
<!-- tableterm contains directly pre if there is an index entry before @itemx -->
<!ELEMENT tableterm (item,  (pre | itemx | %indexentry.cmds;)*)>
<!ELEMENT item (#PCDATA | %Inline.line; | itemformat | indexterm)*>
<!ATTLIST item
          %spacesattr;>
<!ELEMENT itemx (#PCDATA | %Inline.line; | itemformat | indexterm)*>
<!ATTLIST itemx
          %spacesattr;>
<!ELEMENT itemformat (#PCDATA | %Inline.line; | indexterm)*>
<!-- begin and end are for definfoenclose command for item content -->
<!ATTLIST itemformat
          command   CDATA #REQUIRED
          begin CDATA #IMPLIED
          end CDATA #IMPLIED>
<!ELEMENT tableitem (%block;)*>

<!ELEMENT multitable ((columnfractions | columnprototypes), beforefirstitem?,
                      thead?, tbody)>
<!ATTLIST multitable
          %blocktablearg;>
<!ELEMENT columnfractions (columnfraction+)>
<!ATTLIST columnfractions
          %lineattr;>
<!ELEMENT columnprototypes (columnprototype+)>
<!ELEMENT columnfraction EMPTY>
<!ATTLIST columnfraction
          value CDATA #REQUIRED>
<!ELEMENT columnprototype (#PCDATA | %Inline.line;)*>
<!ATTLIST columnprototype
          %spacesattr;
          %bracketedattr;>
<!ELEMENT thead (row+)>
<!ELEMENT tbody (row+)>
<!ELEMENT row (entry*)>
<!ELEMENT entry (%block;)*>
<!ATTLIST entry
          %spacesattr;
          command   CDATA #REQUIRED>

<!-- API definitions -->

<!-- def* contains directly pre if there is an index entry before def*x -->
<!ELEMENT deffn (definitionterm, (pre | deffnx | %indexentry.cmds;)*, definitionitem?)>
<!ATTLIST deffn
          %spacesblockattr;>
<!ELEMENT deffnx (definitionterm)>
<!ATTLIST deffnx
          %spacesattr;>
<!ELEMENT defvr (definitionterm, (pre | defvrx | %indexentry.cmds;)*, definitionitem?)>
<!ATTLIST defvr
          %spacesblockattr;>
<!ELEMENT defvrx (definitionterm)>
<!ATTLIST defvrx
          %spacesattr;>
<!ELEMENT deftypefn (definitionterm, (pre | deftypefnx | %indexentry.cmds;)*, definitionitem?)>
<!ATTLIST deftypefn
          %spacesblockattr;>
<!ELEMENT deftypefnx (definitionterm)>
<!ATTLIST deftypefnx
          %spacesattr;>
<!ELEMENT deftypeop (definitionterm, (pre | deftypeopx | %indexentry.cmds;)*, definitionitem?)>
<!ATTLIST deftypeop
          %spacesblockattr;>
<!ELEMENT deftypeopx (definitionterm)>
<!ATTLIST deftypeopx
          %spacesattr;>
<!ELEMENT deftypevr (definitionterm, (pre | deftypevrx | %indexentry.cmds;)*, definitionitem?)>
<!ATTLIST deftypevr
          %spacesblockattr;>
<!ELEMENT deftypevrx (definitionterm)>
<!ATTLIST deftypevrx
          %spacesattr;>
<!ELEMENT defcv (definitionterm, (pre | defcvx | %indexentry.cmds;)*, definitionitem?)>
<!ATTLIST defcv
          %spacesblockattr;>
<!ELEMENT defcvx (definitionterm)>
<!ATTLIST defcvx
          %spacesattr;>
<!ELEMENT deftypecv (definitionterm, (pre | deftypecvx | %indexentry.cmds;)*, definitionitem?)>
<!ATTLIST deftypecv
          %spacesblockattr;>
<!ELEMENT deftypecvx (definitionterm)>
<!ATTLIST deftypecvx
          %spacesattr;>
<!ELEMENT defop (definitionterm, (pre | defopx | %indexentry.cmds;)*, definitionitem?)>
<!ATTLIST defop
          %spacesblockattr;>
<!ELEMENT defopx (definitionterm)>
<!ATTLIST defopx
          %spacesattr;>
<!ELEMENT deftp (definitionterm, (pre | deftpx | %indexentry.cmds;)*, definitionitem?)>
<!ATTLIST deftp
          %spacesblockattr;>
<!ELEMENT deftpx (definitionterm)>
<!ATTLIST deftpx
          %spacesattr;>
<!ELEMENT defun (definitionterm, (pre | defunx | %indexentry.cmds;)*, definitionitem?)>
<!ATTLIST defun
          %spacesblockattr;>
<!ELEMENT defunx (definitionterm)>
<!ATTLIST defunx
          %spacesattr;>
<!ELEMENT defmac (definitionterm, (pre | defmacx | %indexentry.cmds;)*, definitionitem?)>
<!ATTLIST defmac
          %spacesblockattr;>
<!ELEMENT defmacx (definitionterm)>
<!ATTLIST defmacx
          %spacesattr;>
<!ELEMENT defspec (definitionterm, (pre | defspecx | %indexentry.cmds;)*, definitionitem?)>
<!ATTLIST defspec
          %spacesblockattr;>
<!ELEMENT defspecx (definitionterm)>
<!ATTLIST defspecx
          %spacesattr;>
<!ELEMENT defvar (definitionterm, (pre | defvarx | %indexentry.cmds;)*, definitionitem?)>
<!ATTLIST defvar
          %spacesblockattr;>
<!ELEMENT defvarx (definitionterm)>
<!ATTLIST defvarx
          %spacesattr;>
<!ELEMENT defopt (definitionterm, (pre | defoptx | %indexentry.cmds;)*, definitionitem?)>
<!ATTLIST defopt
          %spacesblockattr;>
<!ELEMENT defoptx (definitionterm)>
<!ATTLIST defoptx
          %spacesattr;>
<!ELEMENT deftypefun (definitionterm, (pre | deftypefunx | %indexentry.cmds;)*, definitionitem?)>
<!ATTLIST deftypefun
          %spacesblockattr;>
<!ELEMENT deftypefunx (definitionterm)>
<!ATTLIST deftypefunx
          %spacesattr;>
<!ELEMENT deftypevar (definitionterm, (pre | deftypevarx | %indexentry.cmds;)*, definitionitem?)>
<!ATTLIST deftypevar
          %spacesblockattr;>
<!ELEMENT deftypevarx (definitionterm)>
<!ATTLIST deftypevarx
          %spacesattr;>
<!ELEMENT defivar (definitionterm, (pre | defivarx | %indexentry.cmds;)*, definitionitem?)>
<!ATTLIST defivar
          %spacesblockattr;>
<!ELEMENT defivarx (definitionterm)>
<!ATTLIST defivarx
          %spacesattr;>
<!ELEMENT deftypeivar (definitionterm, (pre | deftypeivarx | %indexentry.cmds;)*, definitionitem?)>
<!ATTLIST deftypeivar
          %spacesblockattr;>
<!ELEMENT deftypeivarx (definitionterm)>
<!ATTLIST deftypeivarx
          %spacesattr;>
<!ELEMENT defmethod (definitionterm, (pre | defmethodx | %indexentry.cmds;)*, definitionitem?)>
<!ATTLIST defmethod
          %spacesblockattr;>
<!ELEMENT defmethodx (definitionterm)>
<!ATTLIST defmethodx
          %spacesattr;>
<!ELEMENT deftypemethod (definitionterm, (pre | deftypemethodx | %indexentry.cmds;)*, definitionitem?)>
<!ATTLIST deftypemethod
          %spacesblockattr;>
<!ELEMENT deftypemethodx (definitionterm)>
<!ATTLIST deftypemethodx
          %spacesattr;>

<!--
<!ELEMENT definition (definitionterm | definitionitem | indexterm)+>
<!ELEMENT definitionterm (%definition.args; | indexterm)+>
-->
<!ELEMENT definitionterm (indexterm?, (%definition.args;)+)>
<!ELEMENT definitionitem (%block;)*>

<!ENTITY % defargattr
         "%bracketedattr; %spacesattr;">
<!ELEMENT defcategory  (#PCDATA | %Inline.line;)*>
<!ATTLIST defcategory
          %defargattr;
          automatic (%onoff;) 'off'>
<!ELEMENT deffunction  (#PCDATA | %Inline.line;)*>
<!ATTLIST deffunction
          %defargattr;>
<!ELEMENT defvariable  (#PCDATA | %Inline.line;)*>
<!ATTLIST defvariable
          %defargattr;>
<!ELEMENT defparam     (#PCDATA | %Inline.line;)*>
<!ATTLIST defparam
          %defargattr;>
<!ELEMENT defdelimiter (#PCDATA | %Inline.line;)*>
<!ELEMENT deftype      (#PCDATA | %Inline.line;)*>
<!ATTLIST deftype
          %defargattr;>
<!ELEMENT defparamtype (#PCDATA | %Inline.line;)*>
<!ATTLIST defparamtype
          %defargattr;>
<!ELEMENT defdatatype  (#PCDATA | %Inline.line;)*>
<!ATTLIST defdatatype
          %defargattr;>
<!ELEMENT defclass     (#PCDATA | %Inline.line;)*>
<!ATTLIST defclass
          %defargattr;>
<!ELEMENT defclassvar  (#PCDATA | %Inline.line;)*>
<!ATTLIST defclassvar
          %defargattr;>
<!ELEMENT defoperation (#PCDATA | %Inline.line;)*>
<!ATTLIST defoperation
          %defargattr;>

<!-- emacs-page
     Inline elements -->

<!ELEMENT hyphenation (#PCDATA)>

<!-- emphasize -->
<!ELEMENT strong (#PCDATA | %Inline.phrase;)*>
<!ELEMENT emph   (#PCDATA | %Inline.phrase;)*>

<!-- small caps -->
<!ELEMENT sc (#PCDATA | %Inline.phrase;)*>

<!-- fonts -->
<!ELEMENT b  (#PCDATA | %Inline.phrase;)*>
<!ELEMENT i  (#PCDATA | %Inline.phrase;)*>
<!ELEMENT r  (#PCDATA | %Inline.phrase;)*>
<!ELEMENT sansserif   (#PCDATA | %Inline.phrase;)*>
<!ELEMENT slanted     (#PCDATA | %Inline.phrase;)*>
<!ELEMENT titlefont   (#PCDATA | %Inline.phrase;)*>
<!ELEMENT t (#PCDATA | %Inline.phrase;)*>

<!-- markup -->
<!ELEMENT code    (#PCDATA | %Inline.phrase;)*>
<!ELEMENT command (#PCDATA | %Inline.phrase;)*>
<!ELEMENT env     (#PCDATA | %Inline.phrase;)*>
<!ELEMENT file    (#PCDATA | %Inline.phrase;)*>
<!ELEMENT option  (#PCDATA | %Inline.phrase;)*>
<!ELEMENT samp    (#PCDATA | %Inline.phrase;)*>
<!ELEMENT dfn     (#PCDATA | %Inline.phrase;)*>
<!ELEMENT cite    (#PCDATA | %Inline.phrase;)*>
<!ELEMENT key     (#PCDATA | %Inline.phrase;)*>
<!ELEMENT kbd     (#PCDATA | %Inline.phrase;)*>
<!ELEMENT var     (#PCDATA | %Inline.phrase;)*>
<!ELEMENT indicateurl   (#PCDATA | %Inline.phrase;)*>
<!ATTLIST indicateurl
          %spacesattr;>
<!ELEMENT clicksequence (#PCDATA | %Inline.phrase;)*>
<!ELEMENT w       (#PCDATA | %Inline.phrase;)*>
<!ELEMENT asis    (#PCDATA | %Inline.phrase;)*>
<!ELEMENT sub     (#PCDATA | %Inline.phrase;)*>
<!ELEMENT sup     (#PCDATA | %Inline.phrase;)*>
<!ELEMENT verb    (#PCDATA)>
<!ATTLIST verb
          delimiter CDATA #REQUIRED>

<!ELEMENT acronym (acronymword, acronymdesc?)>
<!ATTLIST acronym
          %spacesattr;>
<!ELEMENT acronymword (#PCDATA | %Inline.phrase;)*>
<!ELEMENT acronymdesc (#PCDATA | %Inline.phrase;)*>
<!ATTLIST acronymdesc
          %spacesattr;>

<!ELEMENT abbr (abbrword, abbrdesc?)>
<!ATTLIST abbr
          %spacesattr;>
<!ELEMENT abbrword (#PCDATA | %Inline.phrase;)*>
<!ELEMENT abbrdesc (#PCDATA | %Inline.phrase;)*>
<!ATTLIST abbrdesc
          %spacesattr;>

<!-- math -->
<!ELEMENT math    (#PCDATA | %Inline.phrase;)*>
<!ATTLIST math
          %spacesattr;>
<!ELEMENT dmn     (#PCDATA | %Inline.phrase;)*>

<!-- reference -->
<!ELEMENT anchor (#PCDATA | %Inline.phrase;)*>
<!ATTLIST anchor
          %spacesattr;
          name CDATA #IMPLIED>

<!ELEMENT errormsg (#PCDATA | %Inline.phrase;)*>
<!ATTLIST errormsg
          %spacesattr;>

<!-- inline conditionals -->
<!ELEMENT inlineraw (inlinerawformat, inlinerawcontent)>
<!ATTLIST inlineraw
          %spacesattr;>
<!ELEMENT inlinerawformat (#PCDATA)>
<!ELEMENT inlinerawcontent (#PCDATA | %Inline.phrase;)*>
<!ATTLIST inlinerawcontent
          %spacesattr;>

<!ELEMENT inlinefmt (inlinefmtformat, inlinefmtcontent)>
<!ATTLIST inlinefmt
          %spacesattr;>
<!ELEMENT inlinefmtformat (#PCDATA)>
<!ELEMENT inlinefmtcontent (#PCDATA | %Inline.phrase;)*>
<!ATTLIST inlinefmtcontent
          %spacesattr;>

<!ELEMENT inlineifclear (inlineifclearformat, inlineifclearcontent)>
<!ATTLIST inlineifclear
          %spacesattr;>
<!ELEMENT inlineifclearformat (#PCDATA)>
<!ELEMENT inlineifclearcontent (#PCDATA | %Inline.phrase;)*>
<!ATTLIST inlineifclearcontent
          %spacesattr;>

<!ELEMENT inlineifset (inlineifsetformat, inlineifsetcontent)>
<!ATTLIST inlineifset
          %spacesattr;>
<!ELEMENT inlineifsetformat (#PCDATA)>
<!ELEMENT inlineifsetcontent (#PCDATA | %Inline.phrase;)*>
<!ATTLIST inlineifsetcontent
          %spacesattr;>

<!ELEMENT inlinefmtifelse (inlinefmtifelseformat, inlinefmtifelsecontentif?, inlinefmtifelsecontentelse?)>
<!ATTLIST inlinefmtifelse
          %spacesattr;>
<!ELEMENT inlinefmtifelseformat (#PCDATA)>
<!ELEMENT inlinefmtifelsecontentif (#PCDATA | %Inline.phrase;)*>
<!ATTLIST inlinefmtifelsecontentif
          %spacesattr;>
<!ELEMENT inlinefmtifelsecontentelse (#PCDATA | %Inline.phrase;)*>
<!ATTLIST inlinefmtifelsecontentelse
          %spacesattr;>

<!-- command defined by definfoenclose -->
<!ELEMENT infoenclose  (#PCDATA | %Inline.phrase;)*>
<!ATTLIST infoenclose
          command CDATA #REQUIRED
          begin CDATA #IMPLIED
          end CDATA #IMPLIED>

<!ENTITY % xref.args "xrefnodename?, xrefinfoname?, xrefprinteddesc?,
                xrefinfofile?, xrefprintedname?">
<!ENTITY % xref.attr
          "%spacesattr;
           label CDATA #IMPLIED
           manual CDATA #IMPLIED">

<!ELEMENT xref (%xref.args;)>
<!ATTLIST xref
          %xref.attr;>
<!ELEMENT ref (%xref.args;)>
<!ATTLIST ref
          %xref.attr;>
<!ELEMENT pxref (%xref.args;)>
<!ATTLIST pxref
          %xref.attr;>

<!ELEMENT xrefnodename    (#PCDATA | %Inline.phrase;)*>
<!ELEMENT xrefinfoname    (#PCDATA | %Inline.phrase;)*>
<!ATTLIST xrefinfoname
          %spacesattr;>
<!ELEMENT xrefinfofile    (#PCDATA | %Inline.phrase;)*>
<!ATTLIST xrefinfofile
          %spacesattr;>
<!ELEMENT xrefprintedname (#PCDATA | %Inline.phrase;)*>
<!ATTLIST xrefprintedname
          %spacesattr;>
<!ELEMENT xrefprinteddesc (#PCDATA | %Inline.phrase;)*>
<!ATTLIST xrefprinteddesc
          %spacesattr;>

<!ELEMENT inforef (inforefnodename?, inforefrefname?, inforefinfoname?)>
<!ATTLIST inforef
          %xref.attr;>
<!ELEMENT inforefnodename (#PCDATA | %Inline.phrase;)*>
<!ELEMENT inforefrefname  (#PCDATA | %Inline.phrase;)*>
<!ATTLIST inforefrefname
          %spacesattr;>
<!ELEMENT inforefinfoname (#PCDATA | %Inline.phrase;)*>
<!ATTLIST inforefinfoname
          %spacesattr;>

<!ELEMENT email (emailaddress, emailname?)>
<!ATTLIST email
          %spacesattr;>
<!ELEMENT emailaddress (#PCDATA | %Inline.phrase;)*>
<!ELEMENT emailname (#PCDATA | %Inline.phrase;)*>
<!ATTLIST emailname
          %spacesattr;>

<!ELEMENT uref (urefurl, urefdesc?, urefreplacement?)>
<!ATTLIST uref
          %spacesattr;>
<!ELEMENT url  (urefurl, urefdesc?, urefreplacement?)>
<!ATTLIST url
          %spacesattr;>
<!ELEMENT urefurl         (#PCDATA | %Inline.phrase;)*>
<!ELEMENT urefdesc        (#PCDATA | %Inline.phrase;)*>
<!ATTLIST urefdesc
          %spacesattr;>
<!ELEMENT urefreplacement (#PCDATA | %Inline.phrase;)*>

<!ELEMENT footnote (%block;)*>
<!ATTLIST footnote
          %spacesattr;>

<!-- deprecated -->

<!ELEMENT ctrl             (#PCDATA | %Inline.phrase;)*>
<!ELEMENT refill           EMPTY>
<!ELEMENT quote-arg        EMPTY>
<!ELEMENT allow-recursion  EMPTY>

<!-- index commands -->

<!ENTITY % indexcmdattr
         "%spacesattr;
          index CDATA #IMPLIED">

<!ELEMENT defindex  EMPTY>
<!ATTLIST defindex
          %lineattr;
          value     NMTOKEN #REQUIRED>
<!ELEMENT defcodeindex  EMPTY>
<!ATTLIST defcodeindex
          %lineattr;
          value     NMTOKEN #REQUIRED>
<!ELEMENT synindex  EMPTY>
<!ATTLIST synindex
          %lineattr;
          from      NMTOKEN #REQUIRED
          to        NMTOKEN #REQUIRED>
<!ELEMENT syncodeindex  EMPTY>
<!ATTLIST syncodeindex
          %lineattr;
          from      NMTOKEN #REQUIRED
          to        NMTOKEN #REQUIRED>
<!ELEMENT indexterm (#PCDATA | %Inline.line;)*>
<!ATTLIST indexterm
          index         CDATA #IMPLIED
          mergedindex   CDATA #IMPLIED
          number        CDATA #REQUIRED
          incode    (%zeroone;) #IMPLIED>
<!ELEMENT indexcommand (indexterm)>
<!ATTLIST indexcommand
          %indexcmdattr;
          command   CDATA #REQUIRED>
<!ELEMENT cindex (indexterm)>
<!ATTLIST cindex
          %indexcmdattr;>
<!ELEMENT findex (indexterm)>
<!ATTLIST findex
          %indexcmdattr;>
<!ELEMENT kindex (indexterm)>
<!ATTLIST kindex
          %indexcmdattr;>
<!ELEMENT pindex (indexterm)>
<!ATTLIST pindex
          %indexcmdattr;>
<!ELEMENT tindex (indexterm)>
<!ATTLIST tindex
          %indexcmdattr;>
<!ELEMENT vindex (indexterm)>
<!ATTLIST vindex
          %indexcmdattr;>
<!ELEMENT printindex EMPTY>
<!ATTLIST printindex
          %lineattr;
          value     NMTOKEN #REQUIRED>

<!-- unusual insertions and other -->

<!ELEMENT accent (#PCDATA | accent | dotless)*>
<!ATTLIST accent
          %bracketedattr;
          %spacesattr;
          type        CDATA #REQUIRED>

<!ELEMENT bye EMPTY>

<!ELEMENT click  EMPTY>
<!ATTLIST click
          command        CDATA #REQUIRED>

<!ELEMENT dotless (#PCDATA)>

<!ELEMENT spacecmd EMPTY>
<!ATTLIST spacecmd
          type (%spacetype;) #IMPLIED>

<!ELEMENT today EMPTY>

<!ELEMENT U (#PCDATA)>

<!-- emacs-page
     Punctuation and special symbols.  -->

<!ELEMENT punct     (#PCDATA)>
<!ATTLIST punct
          end-of-sentence (yes|no) #IMPLIED>
<!ELEMENT logo      (#PCDATA)>
<!ELEMENT linebreak EMPTY>
<!ELEMENT noeos EMPTY>
<!ELEMENT formfeed EMPTY>

<!ENTITY tex        "<logo>TeX</logo>">
<!ENTITY latex      "<logo>LaTeX</logo>">
<!ENTITY ellipsis   "…">
<!ENTITY lt         "<">
<!ENTITY gt         ">">
<!ENTITY bullet     "•">
<!ENTITY copyright  "©">
<!ENTITY registered "®">
<!ENTITY euro       "€">
<!ENTITY pounds     "£">
<!ENTITY minus      "−">
<!ENTITY linebreak  "<linebreak/>">
<!ENTITY dots       "<punct end-of-sentence='no'>…</punct>">
<!ENTITY enddots    "<punct end-of-sentence='yes'>…</punct>">
<!ENTITY amp        "&">
<!ENTITY lsquo      "‘">
<!ENTITY textlsquo      "‘">
<!ENTITY rsquo      "’">
<!ENTITY textrsquo      "’">
<!ENTITY sbquo      "‚">
<!ENTITY ldquo      "“">
<!ENTITY textldquo      "“">
<!ENTITY rdquo      "”">
<!ENTITY textrdquo      "”">
<!ENTITY bdquo      "„">
<!ENTITY laquo      "«">
<!ENTITY raquo      "»">
<!ENTITY lsaquo     "‹">
<!ENTITY rsaquo     "›">
<!ENTITY textmdash      "—">
<!ENTITY textndash      "–">
<!ENTITY formfeed       "<formfeed/>">
<!ENTITY attrformfeed   "\f">
<!ENTITY period     "<punct end-of-sentence='no'>.</punct>">
<!ENTITY eosperiod  "<punct end-of-sentence='yes'>.</punct>">
<!ENTITY quest      "<punct end-of-sentence='no'>?</punct>">
<!ENTITY eosquest   "<punct end-of-sentence='yes'>?</punct>">
<!ENTITY excl       "<punct end-of-sentence='no'>!</punct>">
<!ENTITY eosexcl    "<punct end-of-sentence='yes'>!</punct>">
<!ENTITY hyphenbreak "">
<!ENTITY slashbreak "/">
<!ENTITY noeos      "<noeos/>">
<!ENTITY arobase    "@">
<!ENTITY lbrace     "{">
<!ENTITY rbrace     "}">
<!ENTITY comma      ",">
<!ENTITY atchar     "@">
<!ENTITY lbracechar "{">
<!ENTITY rbracechar "}">
<!ENTITY backslashchar "\\">
<!ENTITY hashchar   "#">
<!ENTITY nbsp       " ">
<!ENTITY deg        "°">
<!ENTITY expansion  "→">
<!ENTITY point      "★">
<!ENTITY printglyph "⊣">
<!ENTITY errorglyph "error-->">
<!ENTITY result     "⇒">
<!ENTITY le         "≤">
<!ENTITY ge         "≥">
<!ENTITY equiv      "≡">

<!ENTITY auml "ä">
<!ENTITY ouml "ö">
<!ENTITY uuml "ü">
<!ENTITY Auml "Ä">
<!ENTITY Ouml "Ö">
<!ENTITY Uuml "Ü">
<!ENTITY Euml "Ë">
<!ENTITY euml "ë">
<!ENTITY Iuml "Ï">
<!ENTITY iuml "ï">
<!ENTITY yuml "ÿ">
<!ENTITY uml  "¨">

<!ENTITY Aacute "Á">
<!ENTITY Eacute "É">
<!ENTITY Iacute "Í">
<!ENTITY Oacute "Ó">
<!ENTITY Uacute "Ú">
<!ENTITY Yacute "Ý">
<!ENTITY aacute "á">
<!ENTITY eacute "é">
<!ENTITY iacute "í">
<!ENTITY oacute "ó">
<!ENTITY uacute "ú">
<!ENTITY yacute "ý">

<!ENTITY ccedil "ç">
<!ENTITY Ccedil "Ç">

<!ENTITY Acirc "Â">
<!ENTITY Ecirc "Ê">
<!ENTITY Icirc "Ã">
<!ENTITY Ocirc "Ô">
<!ENTITY Ucirc "Û">
<!ENTITY acirc "â">
<!ENTITY ecirc "ê">
<!ENTITY icirc "î">
<!ENTITY ocirc "ô">
<!ENTITY ucirc "û">

<!ENTITY Agrave "À">
<!ENTITY Egrave "È">
<!ENTITY Igrave "Ì">
<!ENTITY Ograve "Ò">
<!ENTITY Ugrave "Ù">
<!ENTITY agrave "à">
<!ENTITY egrave "è">
<!ENTITY igrave "ì">
<!ENTITY ograve "ò">
<!ENTITY ugrave "ù">

<!ENTITY Atilde "Ã">
<!ENTITY Ntilde "Ñ">
<!ENTITY Otilde "Õ">
<!ENTITY atilde "ã">
<!ENTITY ntilde "ñ">
<!ENTITY otilde "õ">

<!ENTITY oslash "ø">
<!ENTITY Oslash "Ø">

<!ENTITY lslash "ł">
<!ENTITY Lslash "Ł">

<!ENTITY THORN  "Þ">
<!ENTITY thorn  "þ">

<!ENTITY eth "ð">
<!ENTITY ETH "Ð">

<!ENTITY ordm "º">
<!ENTITY ordf "ª">

<!ENTITY iexcl "¡">
<!ENTITY pound "£">
<!ENTITY iquest "¿">
<!ENTITY AElig "Æ">
<!ENTITY aelig "æ">
<!ENTITY OElig "Œ">
<!ENTITY oelig "œ">
<!ENTITY Aring "Å">
<!ENTITY aring "å">
<!ENTITY szlig "ß">

<!ENTITY rarr "→">
<!ENTITY rArr "⇒">

<!ENTITY macr "¯">

<!ENTITY backslash "\">


code:
#!/usr/bin/env perl
# $Id$
# Copyright 2011, 2012, 2013 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 3 of the License,
# 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, see <http://www.gnu.org/licenses/>.
#
# Original author: Patrice Dumas.
#
# Output Texinfo command names recognized in the implementation.

BEGIN {
  (my $mydir = $0) =~ s,/[^/]+$,,;
  chomp (my $tpdir = `cd $mydir/../tp && pwd`);
  unshift (@INC, $tpdir);
}

use Texinfo::Common;

print map { "\@$_\n" } sort (keys %Texinfo::Common::all_commands);

repo_name: mthl/texinfo

path: util/txicmdlist

license: mit


code:
#!/usr/bin/env perl
# $Id$
# Copyright 2012, 2013 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 3 of the License,
# 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, see <http://www.gnu.org/licenses/>.
#
# Original author: Patrice Dumas.
#
# Output Texinfo customization variables

use strict;

BEGIN {
  (my $mydir = $0) =~ s,/[^/]+$,,;
  chomp (my $tpdir = `cd $mydir/../tp && pwd`);
  unshift (@INC, $tpdir);
}

use Texinfo::Common;

print Texinfo::Common::_customization_variable_classes();

path: util/txicustomvars


code:
#! /usr/bin/env perl
#
# texixml2texi -- convert Texinfo XML to Texinfo code
#
# Copyright 2012 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 3 of the License,
# 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, see <http://www.gnu.org/licenses/>.
#
# Original author: Patrice Dumas <pertusus@free.fr>

use strict;
use Getopt::Long qw(GetOptions);
# for dirname.
use File::Basename;
use File::Spec;

Getopt::Long::Configure("gnu_getopt");

BEGIN
{
  # emulate -w
  $^W = 1;
  my ($real_command_name, $command_directory, $command_suffix)
     = fileparse($0, '.pl');

  my $datadir = '@datadir@';
  my $package = '@PACKAGE@';
  my $updir = File::Spec->updir();

  my $texinfolibdir;
  my $lib_dir;

  # in-source run
  if (($command_suffix eq '.pl' and !(defined($ENV{'TEXINFO_DEV_SOURCE'})
       and $ENV{'TEXINFO_DEV_SOURCE'} eq 0)) or $ENV{'TEXINFO_DEV_SOURCE'}) {
    my $srcdir = defined $ENV{'srcdir'} ? $ENV{'srcdir'} : $command_directory;
    $texinfolibdir = File::Spec->catdir($srcdir, $updir, 'tp');
    $lib_dir = File::Spec->catdir($texinfolibdir, 'maintain');
    unshift @INC, $texinfolibdir;
  } elsif ($datadir ne '@' .'datadir@' and $package ne '@' . 'PACKAGE@'
           and $datadir ne '') {
    $texinfolibdir = File::Spec->catdir($datadir, $package);
    # try to make package relocatable, will only work if standard relative paths
    # are used
    if (! -f File::Spec->catfile($texinfolibdir, 'Texinfo', 'Parser.pm')
        and -f File::Spec->catfile($command_directory, $updir, 'share',
                                   'texinfo', 'Texinfo', 'Parser.pm')) {
      $texinfolibdir = File::Spec->catdir($command_directory, $updir,
                                          'share', 'texinfo');
    }
    $lib_dir = $texinfolibdir;
    unshift @INC, $texinfolibdir;
  }

  # '@USE_EXTERNAL_LIBINTL @ and similar are substituted in the
  # makefile using values from configure
  if (defined($texinfolibdir)) {
    if ('@USE_EXTERNAL_LIBINTL@' ne 'yes') {
      unshift @INC, (File::Spec->catdir($lib_dir, 'lib', 'libintl-perl', 'lib'));
    }
    if ('@USE_EXTERNAL_EASTASIANWIDTH@' ne 'yes') {
      unshift @INC, (File::Spec->catdir($lib_dir, 'lib', 'Unicode-EastAsianWidth', 'lib'));
    }
    if ('@USE_EXTERNAL_UNIDECODE@' ne 'yes') {
      unshift @INC, (File::Spec->catdir($lib_dir, 'lib', 'Text-Unidecode', 'lib'));
    }
  }
}

use XML::LibXML::Reader;

# gather information on Texinfo XML elements
use Texinfo::Common;
use Texinfo::Convert::TexinfoXML;

my $debug = 0;
my $result_options = Getopt::Long::GetOptions (
 'debug|d' => \$debug,
);

sub command_with_braces($)
{
  my $command = shift;
  if ($command =~ /^[a-z]/i) {
    return "\@".$command.'{}';
  } else {
    return "\@".$command;
  }
}

my %ignored_elements = (
  'prepend' => 1,
  'formalarg' => 1,
  # not ignored everytime
  'indexterm' => 1,
);

my %elements_end_attributes = (
  'accent' => 1,
  'menunode' => 1,
  'menutitle' => 1,
);

my %element_at_commands;
my %entity_texts = (
  'textldquo' => '``',
  'textrdquo' => "''",
  'textmdash' => '---',
  'textndash' => '--',
  'textrsquo' => "'",
  'textlsquo' => '`',
  'formfeed' => "\f",
  # this is not used in pratice, as attrformfeed appears in an
  # attribute and thus is already expanded to text.
  'attrformfeed' => "\f",
);

foreach my $command (keys(%Texinfo::Convert::TexinfoXML::commands_formatting)) {
  if (!ref($Texinfo::Convert::TexinfoXML::commands_formatting{$command})) {
    $entity_texts{$Texinfo::Convert::TexinfoXML::commands_formatting{$command}}
      = command_with_braces($command);
  } else {
    my $spec = $Texinfo::Convert::TexinfoXML::commands_formatting{$command};
    my $element = $spec->[0];
    if ($element eq 'spacecmd') {
      if ($spec->[1] eq 'type') {
        $element_at_commands{$element}->{"type"}->{$spec->[2]}
          = command_with_braces($command);
      } else {
        die "BUG, bad spacecmd specification";
      }
    } else {
      $element_at_commands{$element} = command_with_braces($command);
    }
  }
}

$element_at_commands{'accent'} = 0;

my %arg_elements;
foreach my $command (keys(%Texinfo::Convert::TexinfoXML::commands_args_elements)) {
  my $arg_index = 0;
  foreach my $element_argument (@{$Texinfo::Convert::TexinfoXML::commands_args_elements{$command}}) {
    $arg_elements{$element_argument} = [$arg_index, $command];
    $arg_index++;
  }
}

my %accent_type_command;
foreach my $accent_command (keys(%Texinfo::Convert::TexinfoXML::accent_types)) {
  $accent_type_command{$Texinfo::Convert::TexinfoXML::accent_types{$accent_command}}
    = $accent_command;
}

my %eat_space_elements;
foreach my $element ('texinfo', 'filename') {
  $eat_space_elements{$element} = 1;
}

my $infile = shift @ARGV;

if (!defined($infile) or $infile !~ /\S/) {
  die "Missing file\n";
}

my $reader = XML::LibXML::Reader->new('location' => $infile,
                                       'expand_entities' => 0,
                                    )
       or die "cannot read $infile\n";

#(my $mydir = $0) =~ s,/[^/]*$,,;  # dir we are in
#my $txi_dtd_libdir = "$mydir";  # find tp relative to $0

sub skip_until_end($$)
{
  my $reader = shift;
  my $name = shift;
  while ($reader->read) {
    if ($reader->nodeType() eq XML_READER_TYPE_END_ELEMENT
        and $reader->name eq $name) {
      return;
    }
  }
}

my $eat_space = 0;
my @commands_with_args_stack;

while ($reader->read) {

  # ============================================================ begin debug
  if ($debug) {
    printf STDERR "(args: @commands_with_args_stack) (eat_space $eat_space) %d %d %s %d", ($reader->depth,
                           $reader->nodeType,
                           $reader->name,
                           $reader->isEmptyElement);
    my $value = '';
    if ($reader->hasValue()) {
      $value = $reader->value();
      $value =~ s/\n/\\n/g;
      print STDERR " |$value|";
    }
    if ($reader->nodeType() eq XML_READER_TYPE_ELEMENT
        and $reader->hasAttributes()
        and defined($reader->getAttribute('spaces'))) {
      my $spaces = $reader->getAttribute('spaces');
      print STDERR " spaces:$spaces|";
    }
    print STDERR "\n";
  }
  # ============================================================ end debug

  if ($reader->nodeType() eq XML_READER_TYPE_SIGNIFICANT_WHITESPACE
      and $eat_space) {
    $eat_space = 0;
    next;
  } elsif ($reader->nodeType() eq XML_READER_TYPE_TEXT
      or $reader->nodeType() eq XML_READER_TYPE_WHITESPACE
      or $reader->nodeType() eq XML_READER_TYPE_SIGNIFICANT_WHITESPACE
     ) {
    if ($reader->hasValue()) {
      print $reader->value();
    }
  }
  my $name = $reader->name;
  if ($reader->nodeType() eq XML_READER_TYPE_ELEMENT) {
    if (($name eq 'entry' or $name eq 'indexcommand')
        and $reader->hasAttributes()
        and defined($reader->getAttribute('command'))) {
      $name = $reader->getAttribute('command');
    } elsif ($name eq 'listitem') {
      $name = 'item';
    }
    if ($Texinfo::Convert::TexinfoXML::commands_args_elements{$name}) {
      push @commands_with_args_stack, 0;
    }
    if (exists $element_at_commands{$name}) {
      if ($name eq 'accent') {
        if ($reader->hasAttributes()) {
          if (defined($reader->getAttribute('type'))) {
            my $command = $accent_type_command{$reader->getAttribute('type')};
            print "\@$command"
              if (defined($command));
          }
          if (!defined($reader->getAttribute('spaces'))
              and !(defined($reader->getAttribute('bracketed'))
                    and $reader->getAttribute('bracketed') eq 'off')) {
            print '{';
          }
        } else {
          print '{';
        }
      } elsif (!ref($element_at_commands{$name})) {
        print $element_at_commands{$name};
      } else {
        my ($attribute) = keys(%{$element_at_commands{$name}});
        if ($reader->hasAttributes()
            and defined($reader->getAttribute($attribute))) {
          print
            $element_at_commands{$name}->{$attribute}->{$reader->getAttribute($attribute)};
        }
      }
    } elsif (exists($Texinfo::Common::brace_commands{$name})) {
      print "\@${name}{";
      if ($name eq 'verb' and $reader->hasAttributes()
          and defined($reader->getAttribute('delimiter'))) {
        print $reader->getAttribute('delimiter');
      }
    } elsif (exists($Texinfo::Common::block_commands{$name})) {
      print "\@$name";
      if ($name eq 'macro') {
        if ($reader->hasAttributes() and defined($reader->getAttribute('line'))) {
          print $reader->getAttribute('line');
        }
        print "\n";
      }
    } elsif (defined($Texinfo::Common::misc_commands{$name})) {
      if ($reader->hasAttributes()
          and defined($reader->getAttribute('originalcommand'))) {
        $name = $reader->getAttribute('originalcommand');
      }
      if ($name eq 'documentencoding' and $reader->hasAttributes()
          and defined($reader->getAttribute('encoding'))) {
        my ($texinfo_encoding, $perl_encoding, $output_encoding)
         = Texinfo::Encoding::encoding_alias($reader->getAttribute('encoding'));

        if (defined($perl_encoding)) {
          if ($debug) {
            print STDERR "Using encoding $perl_encoding\n";
          }
          binmode(STDOUT, ":encoding($perl_encoding)");
        }
      }
      print "\@$name";
      if ($reader->hasAttributes() and defined($reader->getAttribute('line'))) {
        my $line = $reader->getAttribute('line');
        $line =~ s/\\\\/\x{1F}/g;
        $line =~ s/\\f/\f/g;
        $line =~ s/\x{1F}/\\/g;
        print $line;
      }
      if ($name eq 'set' or $name eq 'clickstyle') {
        skip_until_end($reader, $name);
      }
    } elsif ($arg_elements{$name}) {
      if ($reader->hasAttributes()
          and defined($reader->getAttribute('automatic'))
          and $reader->getAttribute('automatic') eq 'on') {
        skip_until_end($reader, $name);
        next;
      }
      while ($arg_elements{$name}->[0]
             and $commands_with_args_stack[-1] < $arg_elements{$name}->[0]) {
        $commands_with_args_stack[-1]++;
        print ',';
      }
    } elsif ($ignored_elements{$name}) {
      my $keep_indexterm = 0;
      if ($name eq 'indexterm') {
        my $node_path = $reader->nodePath();
        if ($node_path =~ m:([a-z]+)/indexterm$:) {
          my $parent = $1;
          if ($parent =~ /^[a-z]?[a-z]index$/ or $parent eq 'indexcommand') {
            $keep_indexterm = 1;
          }
        }
      }
      if (!$keep_indexterm) {
        skip_until_end($reader, $name);
        next;
      }
    } elsif ($name eq 'formattingcommand') {
      if ($reader->hasAttributes()
          and defined($reader->getAttribute('command'))) {
        print '@'.$reader->getAttribute('command');
      }
    # def* automatic
    } elsif ($reader->hasAttributes()
          and defined($reader->getAttribute('automatic'))
          and $reader->getAttribute('automatic') eq 'on') {
      skip_until_end($reader, $name);
      # eat the following space
      $reader->read();
    } elsif ($eat_space_elements{$name}) {
      $eat_space = 1;
    } else {
      print STDERR "UNKNOWN $name\n" if ($debug);
    }
    if ($reader->hasAttributes()) {
      if (defined($reader->getAttribute('bracketed'))
          and $reader->getAttribute('bracketed') eq 'on') {
        print '{';
      }
      if (defined($reader->getAttribute('spaces'))) {
        my $spaces = $reader->getAttribute('spaces');
        $spaces =~ s/\\n/\n/g;
        $spaces =~ s/\\f/\f/g;
        print $spaces;
      }
      if (defined($reader->getAttribute('leadingtext'))) {
        print $reader->getAttribute('leadingtext');
      }
    }
    if ($Texinfo::Common::item_line_commands{$name}
        and $reader->hasAttributes()
        and defined($reader->getAttribute('commandarg'))) {
      print '@'.$reader->getAttribute('commandarg');
    }
  } elsif ($reader->nodeType() eq XML_READER_TYPE_END_ELEMENT) {
    if ($Texinfo::Convert::TexinfoXML::commands_args_elements{$name}) {
      pop @commands_with_args_stack;
    }
    if ($reader->hasAttributes()) {
      if (defined($reader->getAttribute('bracketed'))
          and $reader->getAttribute('bracketed') eq 'on') {
        print '}';
      }
    }
    if (exists ($Texinfo::Common::brace_commands{$name})) {
      if ($name eq 'verb' and $reader->hasAttributes()
          and defined($reader->getAttribute('delimiter'))) {
        print $reader->getAttribute('delimiter');
      }
      print '}';
    } elsif (exists($Texinfo::Common::block_commands{$name})) {
      my $end_spaces;
      if ($reader->hasAttributes()
          and defined($reader->getAttribute('endspaces'))) {
        $end_spaces = $reader->getAttribute('endspaces');
      }
      $end_spaces = ' ' if (!defined($end_spaces) or $end_spaces eq '');
      print "\@end".$end_spaces."$name";
    } elsif (defined($Texinfo::Common::misc_commands{$name})) {
      if ($Texinfo::Common::root_commands{$name} and $name ne 'node') {
        $eat_space = 1;
      }
    } elsif ($elements_end_attributes{$name}) {
      if ($name eq 'accent') {
        if ($reader->hasAttributes()) {
          if (!defined($reader->getAttribute('spaces'))
              and !(defined($reader->getAttribute('bracketed'))
                    and $reader->getAttribute('bracketed') eq 'off')) {
            print '}';
          }
        } else {
          print '}';
        }
      } elsif ($reader->hasAttributes()
               and defined($reader->getAttribute('separator'))) {
        print $reader->getAttribute('separator');
      }
    } elsif ($eat_space_elements{$name}) {
      $eat_space = 1;
    } else {
      print STDERR "END UNKNOWN $name\n" if ($debug);
    }
    if ($reader->hasAttributes()
        and defined($reader->getAttribute('trailingspaces'))) {
      my $trailingspaces = $reader->getAttribute('trailingspaces');
      $trailingspaces =~ s/\\f/\f/g;
      print $trailingspaces;
    }
  } elsif ($reader->nodeType() eq XML_READER_TYPE_ENTITY_REFERENCE) {
    if (defined($entity_texts{$name})) {
      print $entity_texts{$name};
    }
  } elsif ($reader->nodeType() eq XML_READER_TYPE_COMMENT) {
    my $comment;
    if ($reader->hasValue()) {
      $comment = $reader->value();
      $comment =~ s/^ (comment|c)//;
      my $command = $1;
      $comment =~ s/ $//;
      print "\@${command}$comment";
    }
  } elsif ($reader->nodeType() eq XML_READER_TYPE_DOCUMENT_TYPE) {
    $eat_space = 1;
  }
}

1;


code:
bashy2
------

**bashy2** is an irc bot used on irc.sdf.org.

Join sdf at http://sdf.org/ or sdf-eu at https://sdfeu.org/.

Listen to http://anonradio.net/.

license: unknown


code:
#!/usr/bin/env bash

# This file is part of bashy2, an irc bot used on irc.sdf.org.

# Copyright (C) 2015-2016 mlaine@sdfeu.org, grugly@sdf.org
# Copyright (C) 2017 mlaine@sdfeu.org

# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to deal
# in the Software without restriction, including without limitation the rights
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
# copies of the Software, and to permit persons to whom the Software is
# furnished to do so, subject to the following conditions:

# The above copyright notice and this permission notice shall be included in
# all copies or substantial portions of the Software.

# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
# SOFTWARE.

#------------------------------------------------------------------------------

debug=1

server="$1"
irc_port=6667
irc_host='irc.sdf.org'
irc_pass="$HOME/.oline"
modes=12

cmd_dir='./bits/commands'

if [[ "$server" = 'us' ]]; then
    auth_host='sdf.org'
    auth_host2='sdf-eu.org'
    bot_user='BASHy2'
    bot_user2='BASHy2-EU'
    bot_nick='BASHy2'
    bot_real='A BASH Bot'
elif [[ "$server" = 'eu' ]]; then
    auth_host='sdf-eu.org'
    auth_host2='sdf.org'
    bot_user='BASHy2-EU'
    bot_user2='BASHy2'
    bot_nick='BASHy2-EU'
    bot_real='BASHy2 in Europe'
else
    printf '\n%s\n\n' 'Supply argument us|eu if running from sdf-us|sdf-eu.'
    exit 1
fi

function init {
    source './bits/vitalbits.sh'
    source './bits/nonvitalbits.sh'
    exec 3<>"/dev/tcp/$irc_host/$irc_port" || return 1
    send 'user' "$bot_user" "$bot_real"
    send 'nick' "$bot_nick"
}

function recon {
    if (( "$i" <= '10' )); then
        sleep 30 && init
        let "i++"
    else
        sleep 300 && init
    fi
}

function main {
    i=0; init
    while true; do
        IFS=$' \t\r' read -ru3 -a data
        if [[ ! "$data" ]]; then
            recon
        else
            debug 'IN:' "${data[@]}"
            if [[ "${data[0]}" = 'PING' ]]; then
                send 'pong' "${data[1]}"
                continue
            fi
            case "${data[1]}" in
                'PRIVMSG')
                    priv "${data[@]}" ;;
                'JOIN')
                    user_join "${data[@]}" ;;
                'QUIT')
                    user_quit "${data[@]}" ;;
                '001')
                    send 'oper' "$bot_user" "$(head -1 "$irc_pass")"
                    chan="$bot_user2"; send 'pm' 'foo'
                    join && eval i=0
                    sleep 15 && chtopic &&
                    sleep 15 && serv 'upall' & ;;
                '332'|'331')
                    chtopic "${data[@]}" ;;
                '352'|'315')
                    upall "${data[@]}" ;;
                '311'|'319')
                    up "${data[@]}" ;;
            esac
        fi
    done
}

main


code: Welcome to #anonradio | run cmus && :add http://anonradio.net:8000/anonradio.m3u && relax

path: bits/channels/#anonradio


code: NSA. can't hack Art, join us!

path: bits/channels/#artrev


code: A place for testing bots.

path: bits/channels/#bots


code: Welcome to #helpdesk | Questions? This is the place | If no one is active, we'll be back soon. This means wait more than 2 mins. | Forgot your passwd? See http://sdf.org/?faq?BASICS?12

path: bits/channels/#helpdesk


code: Welcome to #sdf | http://xkcd.com/1782/ | /j #anonradio

path: bits/channels/#sdf


code: Vim, the great editor for coders and prose writers!

path: bits/channels/#vim


code:
#!/usr/bin/env bash

# mlaine@sdfeu

source '../say.sh'

ch="$2"

say "$ch" "$(curl -m 5 -s http://mlaine.sdfeu.org/bashy | tail -n +5 | shuffle -f - | head -1)"


code:
#!/usr/bin/env bash

# mlaine@sdfeu

source '../say.sh'

ch="$2"

cmds=(*); foo=()
for cmd in "${cmds[@]}"; do
    foo+=("!$cmd")
done

say "$ch" "Available commands: ${foo[*]}"

path: bits/commands/commands


code:
#!/usr/bin/env bash

# mlaine@sdfeu

source '../say.sh'
cd '../faqfiles'

nick="$1"
chan="$2"
args=("${@:3}")
faq="${args[0]}"

if [[ "${#args[@]}" -ge 2 && "${args[-2]}" = '>' &&
    ! "${args[-1]}" =~ '#' ]]; then
    chan="${args[-1]}"
fi

if [[ -f "$faq" ]]; then
    readarray -t msg < "$faq"
else
    faqs=(*)
    msg="Available topics: ${faqs[*]}"
fi

say "$chan" "${msg[@]}"

path: bits/commands/faq


code:
#!/usr/bin/env bash

# mlaine@sdfeu

source '../say.sh'

nick="$1"
args=("${@:3}")

if [[ "${#args[@]}" -ge 2 && "${args[-2]}" = '>' &&
    ! "${args[-1]}" =~ '#' ]]; then
    ch="${args[-1]}"
else
    ch="$nick"
fi

msg=(
    '/*'
    'Hi there! I am the sdf irc network bot.'
    'I provide many commands answering questions frequently asked.'
    "The most important of these is the command '!faq'."
    "All available commands can be listed with '!commands'."
    ' '
    'Before going any further, PLEASE do spend some time with me here'
    'in private and experiment with the commands. Also note that at'
    'any time you may /msg BASHy2[-EU] and avoid spammming on channels.'
    'Any questions left unanswered are welcomed in #helpdesk.'
    ' '
    'This message is sent on join to anyone who has not been active on'
    'any channel BASHy2[-EU] is on.'
    '*/'
)

say "$ch" "${msg[@]}"

path: bits/commands/help


code:
#!/usr/bin/env bash

# mlaine@sdfeu

source '../say.sh'

ch="$2"

say "$ch" "$(oneliner)"

path: bits/commands/oneliner


code:
#!/usr/bin/env bash

# mlaine@sdfeu

source '../say.sh'

ch="$2"
pm="$(pom)"

say "$ch" "${pm/0f/%}"

path: bits/commands/pom


code:
#!/usr/bin/env bash

# odie@sdf

source '../say.sh'

chan="$2"
nick="$3"

if [[ -n "$nick" && ! "$nick" =~ [^[:alnum:]_-] && "${nick::1}" != '-' ]]; then
    read -ra seen <<< "$(grep "^$nick " '../data/seen')"
    if [[ -z "$seen" ]]; then
        msg="The user $nick was not found."
    else
        msg="$nick was last seen on ${seen[@]:1:3} in ${seen[4]}."
    fi
else
    msg='Please use the following syntax: !seen <nickname>.'
fi

say "$chan" "$msg"

path: bits/commands/seen


code:
#!/usr/bin/env bash

# niro@sdf

# The wrapped command $() has several parts to it so I've described
# what each part does below.

# L32 Scrape url quietly with 5 second timeout
# L33 Remove newlines
# L34 Remove leading whitespace and remove first occurance of <h3>
# L35 Squash all spaces to single spaces
# L36 Use <h3> as delimeter and print $1 column
# L37 Strip all HTML tags
# L38 Cut output to IRC acceptable maximum (first 512 characters)

source '../say.sh'

nick="$1"
chan="$2"
args=("${@:3}")
req="${args[0]}"

if [[ "${#args[@]}" -ge 2 && "${args[-2]}" = '>' &&
    ! "${args[-1]}" =~ '#' ]]; then
    chan="${args[-1]}"
fi

regex='^[1-9]$'
stat='http://status.sdf.org/ (hosted independently)'

scrape() {
    wget -T 5 -qO - http://status.sdf.org |\
    tr -d '\n' |\
    sed -e '/^[[:blank:]]*$/d; s/^<h3>//;' |\
    tr -s ' ' |\
    awk -F'<h3>' -v i="$1" '{print $i}' |\
    sed -e 's/<[^>]*>/ /g' |\
    cut -c1-512
}

if [[ "$req" =~ $regex ]]; then
    body="$(scrape "$req")"
else
    body="$(scrape 1)"
fi

if [[ -z "$body" ]]; then
    say "$chan" "Could not scrape status information from $stat."
else
    say "$chan" "*$body*" "scraped from $stat."
fi

path: bits/commands/status


code: # !up implemented in vitalbits.sh, this file is needed for !commands

path: bits/commands/up


code:
#!/usr/bin/env bash

# grugly@sdf

source '../say.sh'

ch="$2"
req="$3"

if [[ $req =~ 'faeroes'|'iceland'|'norge'|'ol'|'sdf'|'vpn'|'vps'|'vps2'|'vps3'|'wm' ]]
then
    msg="$(
        lynx -connect_timeout=5 -dump http://sdf.org/?status |
        grep -m 1 "$req" |
        sed -e 's/^[ \t]*//' | tr -s ' '
    )"
else
    msg="Valid hosts are faeroes, iceland, norge, ol, sdf, vpn, vps, vps2, vps3 and wm."
fi

say "$ch" "$msg"

path: bits/commands/uptime


code:
#!/usr/bin/env bash

# grugly@sdf

source '../say.sh'

ch="$2"
url="$3"
usg='The command !url <url> prints the title in most cases.'
rgx='https?://[-A-Za-z0-9\+&@#/%?=~_|!:,.;]*[-A-Za-z0-9\+&@#/%=~_|]'

if [[ "$url" =~ $rgx ]]; then
    msg="$(
        wget -T 5 -qO - "$url" |
        awk -vRS="</title>" '/<title>/{gsub(/.*<title>/,"");print;exit}'
    )"
fi

[[ -z "$msg" ]] && msg="$usg"

say "$ch" "$msg"

path: bits/commands/url


code:
#!/usr/bin/env bash

# mlaine@sdfeu

source '../say.sh'

nick="$1"
chan="$2"
arg="$3"

if [[ "${#arg}" -eq 4 && ! "$arg" =~ [^[:alpha:]] ]]; then
    site="${arg^^}"
    url="ftp://tgftp.nws.noaa.gov/data/observations/metar/decoded/$site.TXT"
    report="$(curl --connect-timeout 5 -s "$url")"
    if [[ -z "$report" ]]; then
        msg='The requested location is not in the database or the server is down.'
    else
        if [[ "$report" =~ "($site)" ]]; then
            location="$(egrep "\($site\)" <<< "$report")"
        else
            location="$site"
        fi
        weather="$(
            egrep "Temperature:|Relative Humidity:|Weather:|Sky conditions:" <<< "$report"
        )"
        printf -v msg '%s\n%s' "Location: $location" "$weather"
        readarray -t msg <<< "$msg"
    fi
else
    chan="$nick"
    msg=(
        'The command !weather prints NWS METAR observations for the requested location (1st arg).'
        'You must use the ICAO location format, see https://www.notams.faa.gov/common/icao/ for a list.'
        'Observations are available for locations listed in http://tgftp.nws.noaa.gov/data/observations/metar/decoded/.'
    )
fi

say "$chan" "${msg[@]}"

path: bits/commands/weather


code:
Usage of any unattended process is restricted to MetaARPA members only.
This includes tmux, screen, eggdrop, bots, IRC bouncers etc.

path: bits/faqfiles/background


code:
Anything that requires an Admin should go to the bboard.
If you are reading this, your issue will be better handled on the bboard.
To run bboard, use the command 'bboard'. See the man page for help.

path: bits/faqfiles/bboard


code:
You must be a MetaArpa member to have unattended processes.
Please read http://sdf.org/?faq?CHAT?01.
Validation ($3) + Arpa ($36) + Meta ($36 per year) == $75 USD.

path: bits/faqfiles/bot


code: See http://sdf.org/?faq for frequently asked questions.

path: bits/faqfiles/faq


code:
If you have set up password recovery, login as 'new' and type 'recover'.
Otherwise, you may politely contact membership (at) sdf.org.
You may consider making a donation at that time as it will greatly improve your chances of getting a password reset. See also http://sdf.org/?faq?BASICS?12.

path: bits/faqfiles/forgot


code:
The Idle RPG is just what it sounds like: an RPG in which the players idle in the #irpg channel.
In addition to merely gaining levels, players can find items and battle other players.
However, this is all done for you; you just idle!
See http://irpg.demu.red for details about registration, commands and game rules.

path: bits/faqfiles/irpg


code: See http://sdf.org/?join for membership information.

path: bits/faqfiles/join


code: See http://sdf.org/minecraft for details on how to connect to SDF's very own Minecraft server.

path: bits/faqfiles/minecraft


code: The MOTD membership is a special privileged membership for SDF users interested in web based journals, forums, wikis, galleries et cetera. See http://www.motd.org for more information.

path: bits/faqfiles/motd


code:
To create a new account telnet or ssh to sdf.org and login as new.
Examples for doing this are available at http://sdf.org/?signup.
There is also a server in .de, see https://sdfeu.org/ for details.

path: bits/faqfiles/new


code:
Usage of psybnc (or any unattended process) is restricted to MetaARPA members only.
A full list of memebership levels and their features is available at http://sdf.org/?join.

path: bits/faqfiles/psybnc


code:
Prevalidated and validated accounts will expire after a determined period of time.
Arpa and above are exempt from expiration. See http://sdf.org/?faq?MEMBERS?05.

path: bits/faqfiles/purge


code: You can find my source at https://notabug.org/mlaine/bashy2.

path: bits/faqfiles/source


code: See http://sdf.org/?tutorials for a number of SDF tutorials.

path: bits/faqfiles/tutorial


code: If you want to be validated, the best way to do so is to donate $1 ($3 with paypal) or more to SDF; see http://sdf.org/?join#donate.

path: bits/faqfiles/validate


code:
SDF now offers VoIP telephony SIP service for ARPA and above.
To get started see http://sdf.org/index.cgi?tutorials#voip.

path: bits/faqfiles/voip


code:
# Nonvital bits of bashy2

# This file is part of bashy2, an irc bot used on irc.sdf.org.

# Copyright (C) 2016-2017 mlaine@sdfeu.org

# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to deal
# in the Software without restriction, including without limitation the rights
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
# copies of the Software, and to permit persons to whom the Software is
# furnished to do so, subject to the following conditions:

# The above copyright notice and this permission notice shall be included in
# all copies or substantial portions of the Software.

# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
# SOFTWARE.

#------------------------------------------------------------------------------

function welcome {
    local db='./bits/data/seen'
    if [[ "$quiet" -eq 1 && "${chan:1}" = '#helpdesk' &&
            -z "$(grep "^$nick " "$db")" ]]; then
        ( cd "$cmd_dir" && './help' 0 "$nick" ) &
    fi
}

function seen {
    # Based on PRIVMSG events on a channel, updates a database of seen users.
    # The command seen depends on this database.
    local db='./bits/data/seen'
    [[ ! -f "$db" ]] && touch "$db"

    local time="$(date -u +%x\ %R\ %Z)"
    local old="$(grep "^$nick " "$db")"
    local new="$nick $time $chan"
    if [[ -n "$old" ]]; then
        perl -i -pe "s~$old~$new~" "$db"
    else
        printf '%s\n' "$new" >> "$db"
    fi
}


code:
# You should source this function and use it to send your strings to the
# channel, which is the first argument say() takes. Every other argument
# is printed on its own line. Note that you may use arrays as well.

function say {
    a=("$@")
    for str in "${a[@]:1}"; do
        printf 'PRIVMSG %s :%s\n' "${a[0]}" "$str" >&3
    done
}


code:
# Vital bits of bashy2

# This file is part of bashy2, an irc bot used on irc.sdf.org.

# Copyright (C) 2015-2016 mlaine@sdfeu.org, grugly@sdf.org
# Copyright (C) 2017 mlaine@sdfeu.org

# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to deal
# in the Software without restriction, including without limitation the rights
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
# copies of the Software, and to permit persons to whom the Software is
# furnished to do so, subject to the following conditions:

# The above copyright notice and this permission notice shall be included in
# all copies or substantial portions of the Software.

# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
# SOFTWARE.

#------------------------------------------------------------------------------

function debug {
    # Sends data to #bashy2-debug.
    if (( "$debug" == 0 )); then
        printf 'PRIVMSG #bashy2-debug :%s\n' "$*" >&3
    fi
}

function nonvital_join {
    # A parent function for nonvital function calls. Called for every JOIN.
    welcome
}

function nonvital_pm {
    # A parent function for nonvital function calls. Called for every PRIVMSG.
    seen
}

function parse {
    # Parses PRIVMSG formatted information.
    local x="${1%\!*}"
    local y="${1%@*}"
    nick="${x:1}"
    user="${y#*\~}"
    host="${1#*.}"
    chan="$3"
    req="${4:1}"
    cmd="${req:1}"
    args=("${@:5}")
    prefix="${req:0:1}"
}

function multiply {
    # "$(multiply 3 'foo')" -> 'foo foo foo'
    local x="$(printf "%"$1"s")"
    local y="${x// /"$2" }"
    printf '%s\n' "${y% *}"
}

function join {
    # If called with no args, joins all channels. Otherwise joins the channel
    # provided as 1st arg.
    if (( "$#" == 1 )); then
        send 'join' "$1"
        chmode "$1"
    else
        quiet=1
        local chans=('./bits/channels/'*)
        local chlist="${chans[*]##*/}"
        send 'join' "${chlist// /,}"
    fi
}

function chmode {
    # If called with no args, resets channel modes for all channels. Otherwise
    # resets the mode for a channel (1st arg) or lists all chans.
    if (( "$#" == 1 )); then
        local chans="$1"
    else
        local chans=('./bits/channels/'*)
    fi
    if [[ "$1" = 'list' ]]; then
        send 'pm' "Channels: ${chans[*]##*/}"
    else
        for channel in "${chans[@]##*/}"; do
            local mode='+nt-ikLOpQRsVz'
            if [[ "$channel" = '#helpdesk' ]]; then
                local mode="${mode/+/+S}"
            fi
            send 'mode' "$channel" "$mode"
        done
    fi
}

function chtopic {
    # If called with no args, queries the topic of every channel. A query
    # results main() calling chtopic() with args, resulting in the actual
    # setting of topics (should they differ from their default values).
    if (( ! "$#" )); then
        local chans=('./bits/channels/'*)
        for channel in "${chans[@]##*/}"; do
            send 'qtopic' "$channel"
        done
    else
        local ch="$4"
        local foo="${*:5}"
        local topic="${foo:1}"
        local default="$(cat "./bits/channels/$ch" 2>/dev/null)"
        if [[ -n "$default" && "$topic" != "$default" ]]; then
            send 'topic' "$ch" "$default"
        fi
    fi
}

function up {
    # Changes a user's mode based on the output of WHOIS received from the
    # server. WHOIS is issued by the user's request '!up'.
    if [[ "$2" = '311' ]]; then
        nick="$4"
        user="${5/\~/}"
        host="${6#*.}"
        auth
    elif [[ -n "$flag" ]]; then
        local foo=("${@:5}")
        local chans=("${foo[@]//[:~&@%+]/}")
        local name="$(multiply "${#flag}" "$nick")"
        for channel in "${chans[@]}"; do
            if [[ -f "./bits/channels/$channel" ]]; then
                send 'mode' "$channel" "+$flag" "$name"
            fi
        done
    fi
}

function upall {
    # Changes user modes based on the output of WHO received from the server.
    # WHO is issued by serv() 'upall'.
    if [[ "$2" = '315' ]]; then
        local ch="$4"
        sendup "$ch" 'o'
        sendup "$ch" 'h'
        sendup "$ch" 'v'
        ops=(); hops=(); voices=()
    else
        user="${5/\~/}"
        host="${6#*.}"
        nick="$8"
        auth
        case "$flag" in
            'ohv')
                ops+=("$nick")
                hops+=("$nick")
                voices+=("$nick") ;;
            'hv')
                hops+=("$nick")
                voices+=("$nick") ;;
            'v')
                voices+=("$nick") ;;
        esac
    fi
}

function sendup {
    # Simplifies upall().
    local ch="$1"
    case "$2" in
        'o') local nicks=("${ops[@]}") ;;
        'h') local nicks=("${hops[@]}") ;;
        'v') local nicks=("${voices[@]}") ;;
    esac
    local f="$(printf 'f%.0s' $(seq 1 "$modes"))"
    while (( "${#nicks[@]}" > "$modes" )); do
        send 'mode' "$ch" "+${f//f/$2}" "${nicks[*]:0:$modes}"
        local nicks=("${nicks[@]:$modes}")
    done
    if (( "${#nicks[@]}" > 0 )); then
        local f="$(printf 'f%.0s' $(seq 1 "${#nicks[@]}"))"
        send 'mode' "$ch" "+${f//f/$2}" "${nicks[*]}"
    fi
}

function send {
    # A wrapper function to simplify sending messages to the server.
    debug 'OUT:' "$@"
    case "$1" in
        'pong')
            printf 'PONG %s\n' "$2" >&3 ;;
        'pm')
            printf "PRIVMSG %s :%s\n" "$chan" "$2" >&3 ;;
        'mode')
            printf 'MODE %s %s %s\n' "$2" "$3" "$4" >&3 ;;
        'join')
            printf 'JOIN %s\n' "$2" >&3 ;;
        'part')
            printf 'PART %s\n' "$2" >&3 ;;
        'oper')
            printf 'OPER %s %s\n' "$2" "$3" >&3 ;;
        'user')
            printf 'USER %s 0 * :%s\n' "$2" "$3" >&3 ;;
        'nick')
            printf 'NICK %s\n' "$2" >&3 ;;
        'topic')
            printf 'TOPIC %s :%s\n' "$2" "$3" >&3 ;;
        'qtopic')
            printf 'TOPIC %s\n' "$2" >&3 ;;
        'whois')
            printf 'WHOIS %s\n' "$2" >&3 ;;
        'who')
            printf 'WHO %s\n' "$2" >&3 ;;
        'quit')
            printf "QUIT :I'll be back!\n" >&3 ;;
    esac
}

function auth {
    # Authenticates users based on their nick, username and host.
    if [[ "$nick" = "$bot_user" ]]; then
        flag='aohv'
    elif [[ "$host" = "$auth_host" ]]; then
        flag='v'
        if [[ "$nick" = "$user" ]]; then
            case "$(id "$user" 2>/dev/null)" in
                *'600(MetaARPA)'*)
                    flag='ohv' ;;
                *'500(arpa)'*)
                    flag='hv' ;;
            esac
        fi
    elif [[ "$host" = "$auth_host2" ]]; then
        flag='v'
    else
        flag=''
    fi
}

function serv {
    # Maintainer only commands.
    case "$1" in
        'list')
            chmode 'list' "$chan" ;;
        'add')
            local arg="${args[*]}"
            local ch="${arg%% *}"
            if [[ "$arg" =~ ' ' ]]; then
                local topic="${arg#* }"
            fi
            printf '%s\n' "$topic" > "./bits/channels/$ch"
            join "$ch"
            send 'qtopic' "$ch"
            send 'pm' "Added $ch" ;;
        'del')
            local arg="${args[*]}"
            local ch="${arg%% *}"
            rm "./bits/channels/$ch"
            send 'part' "$ch"
            send 'pm' "Deleted $ch" ;;
        'chmode')
            chmode
            send 'pm' 'Channel modes set.' ;;
        'chtopic')
            chtopic
            send 'pm' 'Channel topics set.' ;;
        'upall')
            local chans=('./bits/channels/'*)
            for channel in "${chans[@]##*/}"; do
                send 'who' "$channel"
            done ;;
        'head')
            send 'pm' "$(git log -1 --pretty="format:%h: %s [%an, %ci]")" ;;
        'pull')
            ( git reset --hard && git pull ) &>'/dev/null' &&
            send 'pm' 'Pulled!' ;;
        'reload')
            source './bits/vitalbits.sh'
            source './bits/nonvitalbits.sh'
            send 'pm' 'Reloaded!' ;;
        'restart')
            ( sleep 5 && './bashy2' "$server" & )
            send 'pm' 'Restarting...'
            send 'quit'
            exit 0 ;;
        'debug')
            if (( "$args" == 0 )); then
                debug=0
                send 'pm' 'Debug log available at #bashy2-debug.'
            elif (( "$args" == 1 )); then
                debug=1
                send 'pm' 'Debug logging off.'
            fi ;;
        'quiet')
            quiet=0
            send 'pm' 'I will shut up.' ;;
        'loud')
            quiet=1
            send 'pm' 'Volume up!' ;;
        'die')
            send 'pm' "What'd I do?"
            send 'quit'
            exit 0 ;;
    esac
}

function run {
    # Runs commands.
    if [[ -x "$cmd_dir/$cmd" ]]; then
        ( cd "$cmd_dir" && "./$cmd" "$nick" "$chan" "${args[@]}" ) &
    else
        send 'pm' "'$cmd' not found. See !commands for available commands."
    fi
}

function priv {
    # Processes every PRIVMSG.
    parse "$@"
    if [[ "$chan" = "$bot_user" ]]; then
        if [[ "$user" = "$bot_user2" ]]; then
            quiet=0
            return 0
        fi
        chan="$nick"
    else
        nonvital_pm
    fi
    if [[ "$req" = '!up' ]]; then
        send 'whois' "$nick"
        return 0
    elif [[ -n "$cmd" && ("$quiet" -eq 1 || "$chan" = "$nick") &&
        "$prefix" = '!' && ! "$cmd" =~ [^[:alnum:]_] ]]; then
        run
        return 0
    fi
    if [[ "$prefix" = '%' && -f "./bits/maintainers/$nick" &&
        "$nick" = "$user" && "$host" =~ "$auth_host"|"$auth_host2" ]]; then
        serv "$cmd"
    fi
}

function user_join {
    # Processes every JOIN.
    parse "$@"
    nonvital_join
    auth
    if [[ -n "$flag" ]]; then
        local ch="${chan:1}"
        local name="$(multiply "${#flag}" "$nick")"
        send 'mode' "$ch" "+$flag" "$name"
    fi
    if [[ "$nick" = "$bot_user" ]]; then
        chmode "$ch"
    fi
}

function user_quit {
    # Processes every QUIT.
    local x="${1%\!*}"
    local nick="${x:1}"
    if [[ "$nick" = "$bot_user2" ]]; then
        quiet=1
    fi
}


code:
;; Per-directory local variables for GNU Emacs 23 and later.

((nil
  . ((fill-column . 78)
     (tab-width   .  8)
     (sentence-end-double-space . t)

     ;; For use with 'bug-reference-prog-mode'.
     (bug-reference-url-format . "http://bugs.gnu.org/%s")
     (bug-reference-bug-regexp
      . "<https?://\\(debbugs\\|bugs\\)\\.gnu\\.org/\\([0-9]+\\)>")

     ;; Emacs-Guix
     (eval . (setq-local guix-directory
                         (locate-dominating-file default-directory
                                                 ".dir-locals.el")))

     ;; Geiser
     ;; This allows automatically setting the `geiser-guile-load-path'
     ;; variable when using various Guix checkouts (e.g., via git worktrees).
     (eval . (let ((root-dir-unexpanded (locate-dominating-file
                                         default-directory ".dir-locals.el")))
               ;; While Guix should in theory always have a .dir-locals.el
               ;; (we are reading this file, after all) there seems to be a
               ;; strange problem where this code "escapes" to some other buffers,
               ;; at least vc-mode.  See:
               ;;   https://lists.gnu.org/archive/html/guix-devel/2020-11/msg00296.html
               ;; Upstream report: <https://bugs.gnu.org/44698>
               ;; Hence the following "when", which might otherwise be unnecessary;
               ;; it prevents causing an error when root-dir-unexpanded is nil.
               (when root-dir-unexpanded
                 (let* ((root-dir (expand-file-name root-dir-unexpanded))
                        ;; Workaround for bug https://issues.guix.gnu.org/43818.
                        (root-dir* (directory-file-name root-dir)))

                   (unless (boundp 'geiser-guile-load-path)
                     (defvar geiser-guile-load-path '()))
                   (make-local-variable 'geiser-guile-load-path)
                   (require 'cl-lib)
                   (cl-pushnew root-dir* geiser-guile-load-path
                               :test #'string-equal)))))))

 (c-mode          . ((c-file-style . "gnu")))
 (scheme-mode
  .
  ((indent-tabs-mode . nil)
   (eval . (put 'eval-when 'scheme-indent-function 1))
   (eval . (put 'call-with-prompt 'scheme-indent-function 1))
   (eval . (put 'test-assert 'scheme-indent-function 1))
   (eval . (put 'test-assertm 'scheme-indent-function 1))
   (eval . (put 'test-equalm 'scheme-indent-function 1))
   (eval . (put 'test-equal 'scheme-indent-function 1))
   (eval . (put 'test-eq 'scheme-indent-function 1))
   (eval . (put 'call-with-input-string 'scheme-indent-function 1))
   (eval . (put 'guard 'scheme-indent-function 1))
   (eval . (put 'lambda* 'scheme-indent-function 1))
   (eval . (put 'substitute* 'scheme-indent-function 1))
   (eval . (put 'match-record 'scheme-indent-function 2))

   ;; 'modify-phases' and its keywords.
   (eval . (put 'modify-phases 'scheme-indent-function 1))
   (eval . (put 'replace 'scheme-indent-function 1))
   (eval . (put 'add-before 'scheme-indent-function 2))
   (eval . (put 'add-after 'scheme-indent-function 2))

   (eval . (put 'modify-services 'scheme-indent-function 1))
   (eval . (put 'with-directory-excursion 'scheme-indent-function 1))
   (eval . (put 'with-file-lock 'scheme-indent-function 1))
   (eval . (put 'with-file-lock/no-wait 'scheme-indent-function 1))
   (eval . (put 'with-profile-lock 'scheme-indent-function 1))
   (eval . (put 'with-writable-file 'scheme-indent-function 2))

   (eval . (put 'package 'scheme-indent-function 0))
   (eval . (put 'package/inherit 'scheme-indent-function 1))
   (eval . (put 'origin 'scheme-indent-function 0))
   (eval . (put 'build-system 'scheme-indent-function 0))
   (eval . (put 'bag 'scheme-indent-function 0))
   (eval . (put 'gexp->derivation 'scheme-indent-function 1))
   (eval . (put 'graft 'scheme-indent-function 0))
   (eval . (put 'operating-system 'scheme-indent-function 0))
   (eval . (put 'file-system 'scheme-indent-function 0))
   (eval . (put 'manifest-entry 'scheme-indent-function 0))
   (eval . (put 'manifest-pattern 'scheme-indent-function 0))
   (eval . (put 'substitute-keyword-arguments 'scheme-indent-function 1))
   (eval . (put 'with-store 'scheme-indent-function 1))
   (eval . (put 'with-external-store 'scheme-indent-function 1))
   (eval . (put 'with-error-handling 'scheme-indent-function 0))
   (eval . (put 'with-mutex 'scheme-indent-function 1))
   (eval . (put 'with-atomic-file-output 'scheme-indent-function 1))
   (eval . (put 'call-with-compressed-output-port 'scheme-indent-function 2))
   (eval . (put 'call-with-decompressed-port 'scheme-indent-function 2))
   (eval . (put 'call-with-gzip-input-port 'scheme-indent-function 1))
   (eval . (put 'call-with-gzip-output-port 'scheme-indent-function 1))
   (eval . (put 'call-with-lzip-input-port 'scheme-indent-function 1))
   (eval . (put 'call-with-lzip-output-port 'scheme-indent-function 1))
   (eval . (put 'signature-case 'scheme-indent-function 1))
   (eval . (put 'emacs-batch-eval 'scheme-indent-function 0))
   (eval . (put 'emacs-batch-edit-file 'scheme-indent-function 1))
   (eval . (put 'emacs-substitute-sexps 'scheme-indent-function 1))
   (eval . (put 'emacs-substitute-variables 'scheme-indent-function 1))
   (eval . (put 'with-derivation-narinfo 'scheme-indent-function 1))
   (eval . (put 'with-derivation-substitute 'scheme-indent-function 2))
   (eval . (put 'with-status-report 'scheme-indent-function 1))
   (eval . (put 'with-status-verbosity 'scheme-indent-function 1))
   (eval . (put 'with-build-handler 'scheme-indent-function 1))

   (eval . (put 'mlambda 'scheme-indent-function 1))
   (eval . (put 'mlambdaq 'scheme-indent-function 1))
   (eval . (put 'syntax-parameterize 'scheme-indent-function 1))
   (eval . (put 'with-monad 'scheme-indent-function 1))
   (eval . (put 'mbegin 'scheme-indent-function 1))
   (eval . (put 'mwhen 'scheme-indent-function 1))
   (eval . (put 'munless 'scheme-indent-function 1))
   (eval . (put 'mlet* 'scheme-indent-function 2))
   (eval . (put 'mlet 'scheme-indent-function 2))
   (eval . (put 'run-with-store 'scheme-indent-function 1))
   (eval . (put 'run-with-state 'scheme-indent-function 1))
   (eval . (put 'wrap-program 'scheme-indent-function 1))
   (eval . (put 'with-imported-modules 'scheme-indent-function 1))
   (eval . (put 'with-extensions 'scheme-indent-function 1))
   (eval . (put 'with-parameters 'scheme-indent-function 1))
   (eval . (put 'let-system 'scheme-indent-function 1))

   (eval . (put 'with-database 'scheme-indent-function 2))
   (eval . (put 'call-with-database 'scheme-indent-function 1))
   (eval . (put 'call-with-transaction 'scheme-indent-function 1))
   (eval . (put 'with-statement 'scheme-indent-function 3))
   (eval . (put 'call-with-retrying-transaction 'scheme-indent-function 1))
   (eval . (put 'call-with-savepoint 'scheme-indent-function 1))
   (eval . (put 'call-with-retrying-savepoint 'scheme-indent-function 1))

   (eval . (put 'call-with-container 'scheme-indent-function 1))
   (eval . (put 'container-excursion 'scheme-indent-function 1))
   (eval . (put 'eventually 'scheme-indent-function 1))

   (eval . (put 'call-with-progress-reporter 'scheme-indent-function 1))
   (eval . (put 'with-repository 'scheme-indent-function 2))
   (eval . (put 'with-temporary-git-repository 'scheme-indent-function 2))
   (eval . (put 'with-environment-variables 'scheme-indent-function 1))
   (eval . (put 'with-fresh-gnupg-setup 'scheme-indent-function 1))

   (eval . (put 'with-paginated-output-port 'scheme-indent-function 1))

   ;; This notably allows '(' in Paredit to not insert a space when the
   ;; preceding symbol is one of these.
   (eval . (modify-syntax-entry ?~ "'"))
   (eval . (modify-syntax-entry ?$ "'"))
   (eval . (modify-syntax-entry ?+ "'"))))
 (emacs-lisp-mode . ((indent-tabs-mode . nil)))
 (texinfo-mode    . ((indent-tabs-mode . nil)
                     (fill-column . 72))))

repo_name: maximed/guix


code:
*.eps
*.go
*.log
*.mo
*.pdf
*.png
*.tar.xz
*.tmp
*~
.#*
\#*\#
,*
/ABOUT-NLS
/INSTALL
/aclocal.m4
/autom4te.cache
/build-aux/ar-lib
/build-aux/compile
/build-aux/config.guess
/build-aux/config.rpath
/build-aux/config.sub
/build-aux/depcomp
/build-aux/install-sh
/build-aux/mdate-sh
/build-aux/missing
/build-aux/test-driver
/build-aux/texinfo.tex
/config.status
/configure
/doc/*.1
/doc/.dirstamp
/doc/contributing.*.texi
/doc/guix*.aux
/doc/guix*.cp
/doc/guix*.cps
/doc/guix*.fn
/doc/guix*.fns
/doc/guix*.html
/doc/guix*.info
/doc/guix*.info-[0-9]
/doc/guix*.ky
/doc/guix*.pg
/doc/guix*.toc
/doc/guix*.t2p
/doc/guix*.tp
/doc/guix*.vr
/doc/guix*.vrs
/doc/guix.*.texi
/doc/guix-cookbook.*.texi
/doc/guix.aux
/doc/guix.cp
/doc/guix.cps
/doc/guix.fn
/doc/guix.fns
/doc/guix.html
/doc/guix.info
/doc/guix.info-[0-9]
/doc/guix.ky
/doc/guix.pg
/doc/guix.toc
/doc/guix.t2p
/doc/guix.tp
/doc/guix.vr
/doc/guix.vrs
/doc/os-config-bare-bones.texi
/doc/os-config-desktop.texi
/doc/stamp-vti
/doc/version.texi
/doc/version-*.texi
/etc/committer.scm
/etc/gnu-store.mount
/etc/guix-daemon.cil
/etc/guix-daemon.conf
/etc/guix-daemon.service
/etc/guix-publish.conf
/etc/guix-publish.service
/etc/init.d/guix-daemon
/etc/openrc/guix-daemon
/guix-*
/guix/config.scm
/libformat.a
/libstore.a
/libutil.a
/m4/*
/m4/ChangeLog
/m4/gettext.m4
/m4/iconv.m4
/m4/lib-ld.m4
/m4/lib-link.m4
/m4/lib-prefix.m4
/m4/nls.m4
/m4/po.m4
/m4/progtest.m4
/nix/config.h
/nix/config.h.in
/po/doc/*.mo
/po/doc/*.pot
/po/guix/*.gmo
/po/guix/*.insert-header
/po/guix/*.mo
/po/guix/ChangeLog
/po/guix/Makefile.in.in
/po/guix/Makevars.template
/po/guix/POTFILES
/po/guix/Rules-quot
/po/guix/boldquot.sed
/po/guix/en@boldquot.*
/po/guix/en@quot.*
/po/guix/guix.pot
/po/guix/insert-header.sin
/po/guix/quot.sed
/po/guix/remove-potcdate.sed
/po/guix/remove-potcdate.sin
/po/guix/stamp-po
/po/packages/*.gmo
/po/packages/*.insert-header
/po/packages/*.mo
/po/packages/ChangeLog
/po/packages/Makefile.in.in
/po/packages/Makevars.template
/po/packages/POTFILES
/po/packages/Rules-quot
/po/packages/boldquot.sed
/po/packages/en@boldquot.*
/po/packages/en@quot.*
/po/packages/guix-packages.pot
/po/packages/insert-header.sin
/po/packages/quot.sed
/po/packages/remove-potcdate.sed
/po/packages/remove-potcdate.sin
/po/packages/stamp-po
/pre-inst-env
/release-*
/scripts/guix
/test-env
/test-tmp
/tests/*.trs
/tests/services/*.trs
GPATH
GRTAGS
GTAGS
Makefile
Makefile.in
config.cache
stamp-h[0-9]
.dirstamp
.deps
tmp
/doc/os-config-lightweight-desktop.texi
/nix/scripts/download
/.tarball-version
/.version
/doc/stamp-*
/gnu/packages/bootstrap
/gnu/packages/aux-files/guile-guile-launcher.o
/guile

path: .gitignore


code:
;; This is a Guix channel.

(channel
  (version 0)
  (news-file "etc/news.scm")
  (keyring-reference "keyring")
  (url "https://git.savannah.gnu.org/git/guix.git")) ;the primary URL

path: .guix-channel