Since a major upgrade in pgf, my code does not compile any more. I am trying to make "decorated" source listing, where the decorations can be like highlighting some lines (see the MWE), balls on some lines, images, etc. The decorations are optional, and I pass them as macro arguments. Here goes my MWE

    \documentclass{book}
\usepackage{xcolor}
\usepackage{xkeyval}
\usepackage{listings}
\usepackage{tikz}

\definecolor{ForestGreen}{rgb}{0.0, 0.4, 0.0}
\definecolor{burntorange}{rgb}{0.8, 0.33, 0.0}
\newlength{\mywidth} % Used in defining listing width
\definecolor{ivory}{rgb}{1.0, 1.0, 0.94}
\colorlet{SeparatorColor}{burntorange}

\makeatletter
\define@key{MEMacros}{decorations}{\def\ME@decorations{#1}}
\define@key{MEMacros}{language}{\def\ME@language{#1}}
\define@key{MEMacros}{number}{\def\ME@number{#1}}
\presetkeys{MEMacros}{number=1}{}%
\makeatother

%%Usage \MESourceFile[keys]{source file}{caption}{label}
\makeatletter
\newcommand\MESourceFile[4][]{
\setkeys{MEMacros}{ %language={[ANSI]C},
decorations={},#1}%
\begingroup%
\lstset{    language={[ANSI]C}      }

{\begin{figure*}[h!btp] }
\caption{#3}
\begingroup\edef\x{\endgroup\noexpand\lstinputlisting[label=#4, name=#4] {#2}
}\x
{\end{figure*}}
\endgroup%
}
\makeatother
% % Prepare for some decorations on the listing files
\makeatletter
\newif\iflst@linemark

\begingroup
\pgfmark{line-\lst@name-\the\c@lstnumber-start}%
\endgroup
}

\global\lst@linemarktrue
}

\iflst@linemark
\pgfmark{line-\lst@name-\the\c@lstnumber-first}%
\global\lst@linemarkfalse
\fi
}

\def\tkzlst@fnum#1\relax#2\@STOP{%
\def\@test{#2}%
\ifx\@test\@empty
\def\tkzlst@start{0}%
\else
\@tempcnta=#1\relax
\def\tkzlst@start{\the\@tempcnta}%
\fi
}

\expandafter\tkzlst@fnum\lst@firstnumber\relax\@STOP
\pgfmark{line-\lst@name-\tkzlst@start-start}%
}

% % Put a balloon around some lines in a source
% Usage: \MEHighlightLines{BallonName}{SourceName}{FirstLine}{LastLine}
\newcommand\MEHighlightLines[4]{%
\pgfmathtruncatemacro\pgf@temp{%
#3-1
}%
\iftikzmark{line-#2-\pgf@temp-start}{%
\iftikzmark{line-#2-#3-first}{%
\xdef\b@lines{({pic cs:line-#2-\pgf@temp-start} -| {pic           cs:line-#2-#3-first})}%
}{%
\iftikzmark{line-#2-#3-start}{%
\xdef\b@lines{({pic cs:line-#2-\pgf@temp-start} -| {pic             cs:line-#2-#3-start})}%
}{%
\xdef\b@lines{(pic cs:line-#2-\pgf@temp-start)}%
}%
}%
}{%
\xdef\b@lines{}%
}%
\foreach \k in {#3,...,#4} {%
\iftikzmark{line-#2-\k-first}{%
\xdef\b@lines{\b@lines (pic cs:line-#2-\k-first) }
}{}
\iftikzmark{line-#2-\k-end}{%
\xdef\b@lines{\b@lines (pic cs:line-#2-\k-end) }
}{}
}%
\ifx\b@lines\pgfutil@empty
\else
\edef\pgf@temp{\noexpand\tikz[remember picture,overlay]\noexpand\node[fit={\b@lines}, color=ForestGreen,yshift=-2pt,
draw, fill=green!30, opacity=0.4,  inner sep=1pt, rounded corners=5pt] (#1) {};
}%
\pgf@temp
\fi
}
\makeatother

\begin{document}
\MESourceFile[decorations={
%\MEHighlightLines{HelloWorldsystem}{lst:HelloWorld.c}{1}{3}
}
]{HelloWorld.c}{Hello world}{lst:HelloWorld.c}
\MEHighlightLines{HelloWorldsystem}{lst:HelloWorld.c}{1}{3}
\end{document}


and the great code I want to decorate

#include <stdio.h>

int main()
{
printf("hello, world\n");
}


The intention of the code is to put a highlighted box around lines 1-3. The code, as is, works. It is just to demonstrate that \MEHighlightLines macro works OK. Now you can comment out the pre-last line with that macro and uncomment the line containing the same macro 3 lines above it.

Now you receive the error message

! Undefined control sequence.
\pgfmathsetcount ... \pgfmath@onquick #2\pgfmath@
{\afterassignment \pgfmath...


Since the only difference is that now the macro is passed as argument, rather then called directly, I guess that the cause is hidden in expanding the macro in the new pgf. The argument passing method is

\begingroup\edef\x{\endgroup\noexpand\lstinputlisting[label=#4, name=#4] {#2}
}\x


The error is somewhere in expanding my passed macros in the upgraded pgf. (The decorations must be kept together with the listing, and so do I force them in a \figure. Alternative implementation ideas also welcome (as a workaround), but the best way would be to fix the macro expansion bug.)

Well, the error is quite clear: the code

\begingroup\edef\x{\endgroup\noexpand\lstinputlisting[label=#4, name=#4] {#2}
}\x


should be

\lstinputlisting[label=#4, name=#4] {#2}


There's absolutely no reason for using the \edef\x trick here and the problem is exactly that \ME@decorations doesn't survive \edef because it contains assignments (for instance \pgfmathtruncatemacro).

By the way, also {\begin{figure*}[htbp]} with {\end{figure*}} is wrong and \lstset can well go after \begin{figure*}, so the surrounding \begingroup and \endgroup become superfluous.

Here's a fixed (and reformatted) version.

\documentclass{book}
\usepackage{xcolor}
\usepackage{xkeyval}
\usepackage{listings}
\usepackage{tikz}
\usetikzlibrary{
shapes,
positioning,
arrows,
fit,
backgrounds,
calc,
tikzmark,
}

\definecolor{ForestGreen}{rgb}{0.0, 0.4, 0.0}
\definecolor{burntorange}{rgb}{0.8, 0.33, 0.0}
\newlength{\mywidth} % Used in defining listing width
\definecolor{ivory}{rgb}{1.0, 1.0, 0.94}
\colorlet{SeparatorColor}{burntorange}

\makeatletter
\define@key{MEMacros}{decorations}{\def\ME@decorations{#1}}
\define@key{MEMacros}{language}{\def\ME@language{#1}}
\define@key{MEMacros}{number}{\def\ME@number{#1}}
\presetkeys{MEMacros}{number=1}{}%
\makeatother

%%Usage \MESourceFile[keys]{source file}{caption}{label}
\makeatletter
\newcommand\MESourceFile[4][]{%
\setkeys{MEMacros}{%
%language={[ANSI]C},%
decorations={},%
#1%
}%
\begin{figure*}[h!btp]
\lstset{language={[ANSI]C}}
\caption{#3}
\lstinputlisting[label=#4, name=#4]{#2}%
\end{figure*}
}
%% Prepare for some decorations on the listing files
\newif\iflst@linemark

\begingroup
\pgfmark{line-\lst@name-\the\c@lstnumber-start}%
\endgroup
}

\pgfmark{line-\lst@name-\the\c@lstnumber-end}%
\global\lst@linemarktrue
}

\iflst@linemark
\pgfmark{line-\lst@name-\the\c@lstnumber-first}%
\global\lst@linemarkfalse
\fi
}

\def\tkzlst@fnum#1\relax#2\@STOP{%
\def\@test{#2}%
\ifx\@test\@empty
\def\tkzlst@start{0}%
\else
\@tempcnta=#1\relax
\def\tkzlst@start{\the\@tempcnta}%
\fi
}

\expandafter\tkzlst@fnum\lst@firstnumber\relax\@STOP
\pgfmark{line-\lst@name-\tkzlst@start-start}%
}

%% Put a balloon around some lines in a source
% Usage: \MEHighlightLines{BallonName}{SourceName}{FirstLine}{LastLine}
\newcommand\MEHighlightLines[4]{%
\pgfmathtruncatemacro\pgf@temp{#3-1}%
\iftikzmark{line-#2-\pgf@temp-start}
{%
\iftikzmark{line-#2-#3-first}
{%
\xdef\b@lines{({pic cs:line-#2-\pgf@temp-start} -| {pic cs:line-#2-#3-first})}%
}
{%
\iftikzmark{line-#2-#3-start}
{%
\xdef\b@lines{({pic cs:line-#2-\pgf@temp-start} -| {pic cs:line-#2-#3-start})}%
}
{%
\xdef\b@lines{(pic cs:line-#2-\pgf@temp-start)}
}%
}%
}
{%
\xdef\b@lines{}%
}%
\foreach \k in {#3,...,#4} {%
\iftikzmark{line-#2-\k-first}
{%
\xdef\b@lines{\b@lines (pic cs:line-#2-\k-first) }
}
{}%
\iftikzmark{line-#2-\k-end}
{%
\xdef\b@lines{\b@lines (pic cs:line-#2-\k-end) }
}
{}%
}%
\ifx\b@lines\pgfutil@empty
\else
\edef\pgf@temp{%
\noexpand\tikz[remember picture,overlay]
\noexpand\node[
fit={\b@lines}, color=ForestGreen,yshift=-2pt,
draw, fill=green!30, opacity=0.4,  inner sep=1pt, rounded corners=5pt
] (#1) {};
}%
\pgf@temp
\fi
}
\makeatother

\begin{document}

\MESourceFile[%
decorations={
\MEHighlightLines{HelloWorldsystem}{lst:HelloWorld.c}{1}{3}
}%
]{HelloWorld.c}{Hello world}{lst:HelloWorld.c}

\end{document}


• Thanks a lot!(It looks like I balanced myself: in question tex.stackexchange.com/questions/197224/… I did not use \edef, although I should, here I did, although I should not. :)) – katang May 11 '15 at 19:06
• BTW: in the cited question, you suggested to use \begingroup\edef\x{\endgroup \noexpand\lstset{language={\pb@language}}}\x, so that is why I used the same trick for \ME@decorations. Can you please give me a link, to understand the difference between the two cases? (the MWE was over-simplified) – katang May 11 '15 at 19:12
• @katang That's a very different setting, where an expandable macro is concerned. – egreg May 11 '15 at 19:38
• I still have problem: your solution works with that constant setting, but not with my argument like \begin{figure*}[h!btp] % \lstset{language={[ANSI]C}} \lstset{language={\ME@language}} \caption{#3} \lstinputlisting[label=#4, name=#4]{#2}% \ME@decorations % Decorating comments \end{figure*} – katang May 11 '15 at 19:39
• @katang Ask a new question, please – egreg May 11 '15 at 19:39