summaryrefslogtreecommitdiff
path: root/tex/context/base/xtag-map.tex
diff options
context:
space:
mode:
Diffstat (limited to 'tex/context/base/xtag-map.tex')
-rw-r--r--tex/context/base/xtag-map.tex555
1 files changed, 555 insertions, 0 deletions
diff --git a/tex/context/base/xtag-map.tex b/tex/context/base/xtag-map.tex
new file mode 100644
index 000000000..32648acd7
--- /dev/null
+++ b/tex/context/base/xtag-map.tex
@@ -0,0 +1,555 @@
+%D \module
+%D [ file=xtag-map,
+%D version=2000.12.20,
+%D title=\CONTEXT\ XML Support,
+%D subtitle=Remapping,
+%D author=Hans Hagen,
+%D date=\currentdate,
+%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
+%C
+%C This module is part of the \CONTEXT\ macro||package and is
+%C therefore copyrighted by \PRAGMA. See mreadme.pdf for
+%C details.
+
+%D There is a more versatile mapper available in \type {xtag-rem.tex}!
+
+\beginTEX
+ \endinput
+\endTEX
+
+\writestatus{loading}{Context XML Macros (remap)}
+
+%D A fundamental characteristic of \TEX\ is that much
+%D processing depends on picking up one or more arguments and
+%D acting upon them. In \type {xtag-ini} we have implemented
+%D the normal (high) level interface between \XML\ and
+%D \CONTEXT, and there we already saw some ways to pick up an
+%D element as argument.
+%D
+%D In this module we will implement a preprocessor. An element
+%D that feeds its content to the preprocessor, becomes a token
+%D list consisting of \TEX\ macros, which in turn may expand to
+%D their meanings.
+%D
+%D This module is only tested with \ETEX. In principle we can
+%D make it work with good old \TEX, but we see no objection
+%D against using \ETEX, especially since it's part of every
+%D grown up \TEX\ distribution.
+
+\unprotect
+
+%D A careful reader will notice that we do a full expansion of
+%D the content of the element, although commands that are
+%D protected will stay untouched. In this stage we also
+%D collect key|/|value pairs and pass them onto the \TEX\
+%D macros if needed. Again, we need a fully expandable parser
+%D to handle this, which make the core macros slightly
+%D unreadable.
+%D
+%D The interface presented here evolved from an older module,
+%D written on top of \type {m-sgml}, that could take care of
+%D \MATHML\ (version 1). The implementation here is more
+%D advanced in the sense that it permits all kind of parsers.
+
+\def\findendofXMLelement#1% better use a few expandafters
+ {\if#1>0 \else % space prevents auto \relax
+ \if#1"\endofXMLelementD \else
+ \if#1'\endofXMLelementS \else
+ \if#1/1 \endofXMLelement \else
+ \endofXMLelementN \fi\fi\fi\fi}
+
+\def\endofXMLelementD#1\fi\fi\fi\fi#2"{\fi\fi \findendofXMLelement}
+\def\endofXMLelementS#1\fi\fi\fi\fi#2'{\fi\fi\fi \findendofXMLelement}
+\def\endofXMLelementN#1\fi\fi\fi\fi {\fi\fi\fi\fi\findendofXMLelement}
+\def\endofXMLelement #1\fi\fi\fi\fi#2>{\fi\fi\fi\fi}
+
+\newif\ifremapXMLunknown
+
+\def\doremapXMLelement#1#2#3#4%
+ {\expandafter\ifx\csname\@@XML#1:#2\endcsname\relax#4\else
+ \csname\@@XML#1:#2\endcsname#3%
+ \fi}
+
+\long\def\remapXMLelement#1#2 #3>% todo: we need to get rid of the end /
+ {\if#1!%
+ % ignore all comment
+ \else\if#1?%
+ % ignore all instructions
+ \remapXMLpi#2 #3>%
+ \else\ifcase\findendofXMLelement#2#3>%
+ \if#1/%
+ \expandafter\ifx\csname\@@XML#2:M\endcsname\relax
+ \ifremapXMLunknown\remapXMLone{\s!unknown}{#2}\fi
+ \else
+ \remapXMLone{#2}{}%
+ \fi
+ \else
+ \expandafter\ifx\csname\@@XML#1#2:M\endcsname\relax
+ \ifremapXMLunknown\remapXMLtwo{\s!unknown}{#1#2}\fi
+ \else
+ \remapXMLtwo{#1#2}{#3}%
+ \fi
+ \fi
+ \else
+ \expandafter\ifx\csname\@@XML#1#2:M\endcsname\relax
+ \expandafter\ifx\csname\@@XML#1#2/:M\endcsname\relax
+ \ifremapXMLunknown\remapXMLthree{\s!unknown/}{#1#2}\fi
+ \else
+ \remapXMLthree{#1#2/}{#3}%
+ \fi
+ \else
+ \remapXMLthree{#1#2}{#3}%
+ \fi
+ \fi\fi\fi}
+
+\unexpanded\def\xmlr#1#2{\csname\@@XML#1:#2\endcsname}
+
+\def\@@XMLremap{XMLremap}
+
+\def\remapXMLone#1#2%
+ {\ifcase\csname\@@XMLremap\csname\@@XML#1:M\endcsname\endcsname
+ \or % GCPA
+ \XMLeg\XMLeg
+ \or % GCP-
+ \XMLeg
+ \or % GC-A
+ \XMLeg\XMLeg
+ \or % GC--
+ \XMLeg
+ \or % -CPA
+ \XMLeg
+ \or % -CP-
+ %
+ \or % -C-A
+ \XMLeg
+ \or % -C--
+ %
+ \or % G---
+ \XMLeg
+ \or % GLR-
+ \xmlr{#1}{R}\XMLeg
+ \or % -LR-
+ \xmlr{#1}{R}%
+ \fi}
+
+\def\remapXMLtwo#1#2%
+ {\ifcase\csname\@@XMLremap\csname\@@XML#1:M\endcsname\endcsname
+ \or % GCPA
+ \XMLbg\xmlr{#1}{X}{#2}\XMLbg
+ \or % GCP-
+ \XMLbg\xmlr{#1}{X}{#2}%
+ \or % GC-A
+ \XMLbg\xmlr{#1}{X}\XMLbg
+ \or % GC--
+ \XMLbg\xmlr{#1}{X}%
+ \or % -CPA
+ \xmlr{#1}{X}{#2}\XMLbg
+ \or % -CP-
+ \xmlr{#1}{X}{#2}%
+ \or % -C-A
+ \xmlr{#1}{X}\XMLbg
+ \or % -C--
+ \xmlr{#1}{X}%
+ \or % G---
+ \XMLbg
+ \or % GLR-
+ \XMLbg\xmlr{#1}{L}%
+ \or % -LR-
+ \xmlr{#1}{L}%
+ \fi}
+
+\def\remapXMLthree#1#2%
+ {\ifcase\csname\@@XMLremap\csname\@@XML#1:M\endcsname\endcsname
+ \or % GCPA
+ \XMLbg\xmlr{#1}{X}{#2}\XMLbg\XMLeg\XMLeg
+ \or % GCP-
+ \XMLbg\xmlr{#1}{X}{#2}\XMLeg
+ \or % GC-A
+ \XMLbg\xmlr{#1}{X}\XMLbg\XMLeg\XMLeg
+ \or % GC--
+ \XMLbg\xmlr{#1}{X}\XMLeg
+ \or % -CPA
+ \xmlr{#1}{X}{#2}\XMLbg\XMLeg
+ \or % -CP-
+ \xmlr{#1}{X}{#2}%
+ \or % -C-A
+ \xmlr{#1}{X}\XMLbg\XMLeg
+ \or % -C--
+ \xmlr{#1}{X}%
+ \or % G---
+ \XMLbg\XMLeg
+ \fi}
+
+\@EA\scratchtoks\@EA{\string{} \edef\XMLbg{\the\scratchtoks}
+\@EA\scratchtoks\@EA{\string}} \edef\XMLeg{\the\scratchtoks}
+
+\chardef\XMLremapGCPA = 1 % {\command {arg} { } }
+\chardef\XMLremapGCP = 2 % {\command {arg} } %
+\chardef\XMLremapGCA = 3 % {\command { } }
+\chardef\XMLremapGC = 4 % {\command } %
+\chardef\XMLremapCPA = 5 % \command {arg} { }
+\chardef\XMLremapCP = 6 % \command {arg} %
+\chardef\XMLremapCA = 7 % \command { }
+\chardef\XMLremapC = 8 % \command %
+\chardef\XMLremapG = 9 % { }
+\chardef\XMLremapGLR = 10 % { \bcom \ecom }
+\chardef\XMLremapLR = 11 % \bcom \ecom
+
+\protect
+
+\def\remapXMLpi#1 #2?#3>%
+ {\xmlr{procins/}{X}{#1}{#2}}
+
+\unprotect
+
+%D The remapping is controlled by only a few definition
+%D macros, that both deal with elements. We distinguish
+%D between normal and empty elements.
+%D
+%D \starttypen
+%D \remapXMLsequence [name] [result map] \unexpandablecommand
+%D \remapXMLsequence [name] [result map] \unexpandablecommand
+%D \stoptypen
+%D
+%D The \MATHML\ module demonstrates how these can be used.
+%D The element is converted into a sequence with one or more
+%D of the following components.
+%D
+%D \starttypen
+%D { \command {parameters} {argument} }
+%D \stoptypen
+%D
+%D The following combinations are supported.
+%D
+%D \starttabulatie[|c|c|c|c|c|]
+%D \NC GCPA \NC grouped \NC command \NC parameters \NC argument \NC \NR
+%D \NC GCP \NC grouped \NC command \NC parameters \NC \NC \NR
+%D \NC GCA \NC grouped \NC command \NC \NC argument \NC \NR
+%D \NC GC \NC grouped \NC command \NC \NC \NC \NR
+%D \NC CPA \NC \NC command \NC parameters \NC argument \NC \NR
+%D \NC CP \NC \NC command \NC parameters \NC \NC \NR
+%D \NC CA \NC \NC command \NC \NC argument \NC \NR
+%D \NC C \NC \NC command \NC \NC \NC \NR
+%D \NC G \NC grouped \NC \NC \NC \NC \NR
+%D \stoptabulatie
+%D
+%D Empty elements (singular ones) never get an argument,
+%D which makes sense, since they have at most parameters.
+
+\def\remapXMLsequence{\dotripleargument\doremapXML []}
+\def\remapXMLsingular{\dotripleargument\doremapXML[/]}
+
+\def\doremapXML[#1][#2][#3]%
+ {\doifinstringelse{LR}{#3}
+ {\let\next\doremapXMLtwo}
+ {\let\next\doremapXMLone}%
+ \next[#1][#2][#3]}
+
+\def\doremapXMLone[#1][#2][#3]#4%
+ {\setvalue{\@@XML#2#1:M}{#3}%
+ \setvalue{\@@XML#2#1:X}{#4}}
+
+\def\doremapXMLtwo[#1][#2][#3]#4#5%
+ {\setvalue{\@@XML#2:M}{#3}%
+ \setvalue{\@@XML#2:L}{#4}%
+ \setvalue{\@@XML#2:R}{#5}}
+
+\let\dowithentity\empty
+
+%D We handle unknown elements with:
+
+\remapXMLsingular[procins] [CPA] \doXMLprocins
+
+\def\doXMLprocins#1#2{\dodoXMLprocessor{?#1}{#2}}
+
+\remapXMLsingular [\s!unknown] [CPA] \doXMLunknownSI
+\remapXMLsequence [\s!unknown] [CPA] \doXMLunknownSE
+
+\def\doXMLunknownSI#1#2{\hbox{\tttf[#1]}}
+\def\doXMLunknownSE#1#2{\hbox{\tttf[#1:\enspace\ignorespaces#2\unskip]}}
+
+%D In a similar way, we can remap entities.
+
+\def\remapXMLentity%
+ {\xmlrent}
+
+\unexpanded\def\xmlrent#1%
+ {\getXMLentity{#1}}
+
+%D The remapping is taken care of by the following macro,
+%D which takes three arguments.
+%D
+%D \starttypen
+%D \XMLremapdata{before}{after}{content}
+%D \stoptypen
+%D
+%D After the remapping, the content is executed (expanded)
+%D under the normal \TEX\ catcode regime. The intermediate
+%D result can be traced by turning on the following switch.
+
+\newif\iftraceXMLremapping
+
+\newtoks \everyXMLremapping
+
+\appendtoks
+ \defineXMLentity[tex-hash]{\letterhash}%
+ \defineXMLentity[tex-bar]{\myspecialvert}%
+\to \everyXMLremapping
+
+\def\setnormalXMLentities%
+ {\defineXMLentity[tex-hash]\letterhash
+ \defineXMLentity[tex-dollar]\letterdollar
+ \defineXMLentity[tex-percent]\letterpercent
+ \defineXMLentity[tex-backslash]\letterbackslash
+ \defineXMLentity[tex-hat]\letterhat
+ \defineXMLentity[tex-underscore]\letterunderscore
+ \defineXMLentity[tex-leftbrace]\letterbgroup
+ \defineXMLentity[tex-rightbrace]\letteregroup
+ \defineXMLentity[tex-bar]\letterbar}
+
+\let\XMLremappedpar\empty
+
+\long\def\XMLremapdata#1#2#3%
+ {\bgroup
+ \pushmacro\doXMLelement
+ \pushmacro\doXMLentity % ##2 removes leading spaces
+ \long\def\doXMLelement##1>##2{\remapXMLelement##1 >##2}%
+ \def\doXMLentity ##1;##2{\remapXMLentity{##1}##2}%
+ \enableXML % sets entities
+ \enableXMLexpansion
+ \let\par\XMLremappedpar
+ \the\everyXMLremapping
+ %\ignorelines
+ \catcode`\^^I=\@@space
+ \catcode`\^^M=\@@space
+ \catcode`\^^L=\@@space
+ \catcode`\^^Z=\@@space
+ \xdef\remappedXMLdata{#3\empty}%
+ \let\par\endgraf
+ \popmacro\doXMLentity
+ \popmacro\doXMLelement
+ \disableXMLexpansion
+ \catcode`\{=\@@begingroup
+ \catcode`\}=\@@endgroup
+ \catcode`\\=\@@escape
+ \iftraceXMLremapping
+ \bgroup
+ \convertcommand\remappedXMLdata\to\ascii
+ \tttf\veryraggedright\ascii\par
+ \writestatus{XML}{\ascii}%
+ \egroup
+ \fi
+ #1\scantokens\@EA{\remappedXMLdata\empty\empty}#2%
+ \egroup}
+
+% rename to better names
+
+\newtoks \XMLRtoks
+\newcount \nofXMLRchildren
+
+\def\naturalxmlr#1#2{\getvalue{\@@XML#1:#2}}
+
+\def\ignoreXMLRelement#1#2{}
+\def\normalXMLRelement#1#2{#2}
+
+\let\nextXMLRelement \empty
+\let\firstXMLRelement \empty
+\let\secondXMLRelement\empty
+
+% \def\withnextXMLRelement#1%
+% {\pushmacro\dowithnextXMLRelement
+% \def\dowithnextXMLRelement##1##2##3##4##5%
+% {\popmacro\dowithnextXMLRelement
+% \def\nextXMLRelement{##1{##2}{##3}{##4}{##5}}%
+% #1}%
+% \doifnextcharelse\empty\empty\dowithnextXMLRelement}
+%
+% better and faster:
+
+\def\dowithnextXMLRelement#1#2#3#4#5#6%
+ {\def\nextXMLRelement{#2{#3}{#4}{#5}{#6}}#1}%
+
+\def\withnextXMLRelement#1%
+ {\doifnextcharelse\empty\empty{\dowithnextXMLRelement{#1}}}
+
+\def\withnexttwoXMLRelements#1%
+ {\pushmacro\firstXMLRelement
+ \pushmacro\secondXMLRelement
+ \withnextXMLRelement
+ {\let\firstXMLRelement\nextXMLRelement
+ \withnextXMLRelement
+ {\let\secondXMLRelement\nextXMLRelement
+ #1%
+ \popmacro\secondXMLRelement
+ \popmacro\firstXMLRelement}}}
+
+\def\withnextthreeXMLRelements#1% korter, met two
+ {\pushmacro\firstXMLRelement
+ \pushmacro\secondXMLRelement
+ \pushmacro\thirdXMLRelement
+ \withnextXMLRelement
+ {\let\firstXMLRelement\nextXMLRelement
+ \withnextXMLRelement
+ {\let\secondXMLRelement\nextXMLRelement
+ \withnextXMLRelement
+ {\let\thirdXMLRelement\nextXMLRelement
+ #1%
+ \popmacro\thirdXMLRelement
+ \popmacro\secondXMLRelement
+ \popmacro\firstXMLRelement}}}}
+
+\def\doifXMLRchildelse#1#2#3#4%
+ {\pushmacro\xmlr
+ \def\next{#4}%
+ \def\xmlr##1##2##3##4% the / should be sorted out in the mapper
+ {\rawdoifinsetelse{##1}{#1}
+ {\def\next{#3}}
+ {\doif{##1}{#1/}{\def\next{#3}}}}%
+ #2\empty
+ \popmacro\xmlr
+ \next}
+
+\def\doifXMLRchild#1#2#3%
+ {\pushmacro\xmlr
+ \let\next\empty
+ \def\xmlr##1##2##3##4% the / should be sorted out in the mapper
+ {\rawdoifinsetelse{##1}{#1}
+ {\def\next{#3}}
+ {\doif{##1}{#1/}{\def\next{#3}}}}%
+ #2\empty
+ \popmacro\xmlr
+ \next}
+
+\def\encapsulateXMLRchild#1#2#3#4#5%
+ {\pushmacro\xmlr
+ \def\xmlr##1##2##3##4%
+ {\doifelse{##1}{#1}
+ {\def\next{\doencapsulateXMLRchild{#2}{#3}{#4}{##4}}}
+ {\let\next\empty}%
+ \next}%
+ #5\empty
+ \popmacro\xmlr}
+
+\def\encapsulateXMLRchildren#1#2#3#4#5%
+ {\pushmacro\xmlr
+ \pushmacro\betweenXMLRchild
+ \def\betweenXMLRchild{\def\betweenXMLRchild{#3}}%
+ \def\xmlr##1##2##3##4%
+ {\rawdoifinsetelse{##1}{#1}
+ {\pushmacro\xmlr
+ \let\xmlr\naturalxmlr
+ \betweenXMLRchild\xmlr{##1}{##2}{##3}{##4}%
+ \popmacro\xmlr}
+ {}}%
+ #2#5\empty#4%
+ \popmacro\betweenXMLRchild
+ \popmacro\xmlr}
+
+\def\doencapsulateXMLRchild#1#2#3#4%
+ {\pushmacro\xmlr
+ \pushmacro\betweenXMLRchild
+ \def\betweenXMLRchild{\def\betweenXMLRchild{#2}}%
+ \def\xmlr##1##2##3##4%
+ {\pushmacro\xmlr
+ \let\xmlr\naturalxmlr
+ \betweenXMLRchild\xmlr{##1}{##2}{##3}{##4}%
+ \popmacro\xmlr}%
+ #1#4\empty#3%
+ \popmacro\betweenXMLRchild
+ \popmacro\xmlr}
+
+\let\encapsulateXMLR\doencapsulateXMLRchild
+
+\def\withnextXMLRelementelse#1#2%
+ {\def\xdowithnextXMLRelement##1##2##3##4##5%
+ {\def\nextXMLRelement{##1{##2}{##3}{##4}{##5}}#1}%
+ \def\xnowithnextXMLRelement%
+ {\let\nextXMLRelement\empty#2}%
+ \doifnextcharelse\xmlr\xdowithnextXMLRelement\xnowithnextXMLRelement}
+
+\def\encapsulatenextXMLRelements#1#2#3#4% oude bewaren
+ {\pushmacro\betweenXMLRchild
+ \pushmacro\afterXMLRchild
+ \def\betweenXMLRchild{#1\def\betweenXMLRchild{#2}}%
+ \let\afterXMLRchild\empty
+ \withnextXMLRelementelse
+ {\betweenXMLRchild
+ \def\afterXMLRchild{#3}%
+ \nextXMLRelement
+ \doifnextcharelse\empty\xnowithnextXMLRelement\xdowithnextXMLRelement}
+ {\afterXMLRchild
+ \popmacro\afterXMLRchild
+ \popmacro\betweenXMLRchild}%
+ #4}
+
+\def\collectXMLRchild#1#2%
+ {\XMLRtoks\emptytoks
+ \pushmacro\xmlr
+ \def\xmlr##1##2##3##4%
+ {\doif{##1}{#1}{\appendtoks##4\to\XMLRtoks}}%
+ #2\empty
+ \popmacro\xmlr}
+
+\def\collectbetweenXMLRchild#1#2#3%
+ {\XMLRtoks\emptytoks
+ \pushmacro\xmlr
+ \pushmacro\betweenXMLRchild
+ \def\betweenXMLRchild{\def\betweenXMLRchild{\appendtoks#2\to\XMLRtoks}}%
+ \def\xmlr##1##2##3##4%
+ {\rawdoifinsetelse{##1}{#1}
+ {\betweenXMLRchild\appendtoks\xmlr{##1}{##2}{##3}{##4}\to\XMLRtoks}{}}%
+ #3\empty
+ \popmacro\betweenXMLRchild
+ \popmacro\xmlr}
+
+\def\dorawcollectbetweenXMLR#1#2%
+ {\pushmacro\xmlr
+ \pushmacro\betweenXMLRchild
+ \def\betweenXMLRchild{\def\betweenXMLRchild{#1}}%
+ \def\xmlr##1##2##3##4%
+ {\betweenXMLRchild\appendtoks\xmlr{##1}{##2}{##3}{##4}\to\XMLRtoks}%
+ #2\empty
+ \popmacro\betweenXMLRchild
+ \popmacro\xmlr}
+
+\def\rawcollectbetweenXMLR%
+ {\XMLRtoks\emptytoks\dorawcollectbetweenXMLR}
+
+\def\docollectbetweenXMLR#1%
+ {\dorawcollectbetweenXMLR{\appendtoks#1\to\XMLRtoks}}
+
+\def\collectbetweenXMLR%
+ {\XMLRtoks\emptytoks\docollectbetweenXMLR}
+
+\def\processXMLRchildren#1%
+ {\pushmacro\xmlr
+ \let\xmlr\naturalxmlr
+ #1\empty
+ \popmacro\xmlr}
+
+\def\processXMLRchild#1#2% slow but more versatile
+ {\pushmacro\xmlr
+ \XMLRtoks\emptytoks
+ \def\xmlr##1##2##3##4%
+ {\rawdoifinsetelse{##1}{#1}
+ {\appendtoks\xmlr{##1}{##2}{##3}{##4}\to\XMLRtoks}{}}%
+ #2%
+ \popmacro\xmlr
+ \the\XMLRtoks\empty}
+
+\def\countXMLRchildren#1%
+ {\pushmacro\xmlr
+ \nofXMLRchildren=0
+ \def\xmlr##1##2##3##4{\advance\nofXMLRchildren 1 }
+ #1\empty
+ \popmacro\xmlr}
+
+\def\countXMLRchild#1#2%
+ {\pushmacro\xmlr
+ \nofXMLRchildren=0
+ \def\xmlr##1##2##3##4%
+ {\rawdoifinsetelse{##1}{#1}{\advance\nofXMLRchildren 1 }{}}
+ #2\empty
+ \popmacro\xmlr}
+
+\protect \endinput