# TeX evaluates 'document' code in preamble

I have the error

! LaTeX Error: Missing \begin{document}.
See the LaTeX manual or LaTeX Companion for explanation.
Type H <return> for immediate help.
...


in the following code

\documentclass{scrbook}

\makeatletter

% #1 : package/identifier
% #2 : content
\providecommand{\demo@content@#1}{#2}%
}

\makeatother
\listfiles

\begin{document}
%\PrintDemo{text}
\end{document}


which I do not understand.

Basically I want to save (large) text parts which shall be printed on request as a combination of latex and listings.

-
You must use \expandafter\providecommand\csname demo@content@#1\endcsname{#2} . You can also use the provided commands of etoolbox. See: tex.ac.uk/cgi-bin/texfaq2html?label=csname – Marco Daniel Sep 22 '11 at 15:22

You are misunderstanding how TeX constructs macro names. In the code

\providecommand\AddDemo[2]{%
% #1 : package/identifier
% #2 : content
\providecommand{\demo@content@#1}{#2}%
}


TeX sees a macro \demo@content@ followed by the text supplied as #1. As a result, the later is placed in the input stream, and you see the error about text in the preamble. You need to use \csname to construct the macro name:

\providecommand\AddDemo[2]{%
% #1 : package/identifier
% #2 : content
\expandafter\providecommand\csname demo@content@#1\endcsname{#2}%
}


You need the \expandafter here so that the \csname is constructed before \providecommand is 'executed'.

-
Thank you. However now a similar problem exists on printing the value: \providecommand\PrintDemo[1]{% \ifcsdef{\demo@content@#1}% { % print \demo@content@#1% }% { % error if not defined \PackageError{\packagename}% {% \MessageBreak no demo for '#1' defined \MessageBreak }{} \endinput% } } this results always in '! Undefined control sequence.' \expandafter\csname demo@content@#1\endcsname does not help here – Matthias Pospiech Sep 22 '11 at 15:36
@MatthiasPospiech etoolbox has a number of tools for checking by csname, for example \ifcsdef (which 'partners' \ifdef). – Joseph Wright Sep 22 '11 at 15:39
@MatthiasPospiech You need to use a csname for \ifcsdef, so something like \ifcsdef{demo@content@#1} (notice the lack of a \ ). A csname does not have a leading \ , whereas a control sequence does. – Joseph Wright Sep 22 '11 at 15:50
(Internally \ifcsdef creates a control sequence from its csname argument, whereas \ifdef needs a control sequence argument.) – Joseph Wright Sep 22 '11 at 15:54
\expandafter\providecommand\csname demo@content@#1\endcsname{#2}


You can't append letters to a control sequence name that way, because \demo@content@ is already a token by itself.

-
About 44 seconds faster than me, but I typed more :-) – Joseph Wright Sep 22 '11 at 15:21