Take the 2-minute tour ×
TeX - LaTeX Stack Exchange is a question and answer site for users of TeX, LaTeX, ConTeXt, and related typesetting systems. It's 100% free, no registration required.

I'm writing a package for a software design document. There is a section related to software interfaces between modules, and another section to describe each module. Here there is a summary of interfaces (functions and variables) used by module, collected from previous section using the package collect.

I've created some macro to create interfaces (and collecting needed info), and others to place collected info into desired place, but compiling the document gives me multiple occurrences of following error:

! You can't use a prefix with `\openin'.
<to be read again> 
                   \openin 
l.306 \insertprovidedinterfaces{SUP}

Typing r run pdfLaTeX to the end, and the result is exactly what is expected, but I'm not able to understand/get rid of this messages.

Any hints?

Here is a MWE:

\documentclass[a4paper, oneside, 10pt]{article}
\usepackage[english]{babel}
\usepackage[latin1]{inputenc}
\usepackage[T1]{fontenc}
\usepackage{lmodern}
\renewcommand*\familydefault{\sfdefault} 
\usepackage[table, svgnames]{xcolor}
\usepackage{booktabs}
\usepackage{xparse}
\usepackage{xstring}
\usepackage{longtable}
\usepackage{collect}
\usepackage{tikz}%
\usepackage{hyperref}
%%
\colorlet{IFcolor}{Yellow!30!Blue!20}
\colorlet{IFVcolor}{Yellow!80!Blue!20}
%
% definitions of variables containing modules list, later used
% to avoid re-defining an already defined collection
% pfun -> provided functions
% nfun -> needed functions
% pvar -> provided variables
% nvar -> needed variables
\def\pfuncollectionlist{}
\def\nfuncollectionlist{}
\def\pvarcollectionlist{}
\def\nvarcollectionlist{}
%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% environment for interfaces - functions
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% Usage: 
% param 1: Provider acronym
% param 2: name of function including ()
% param 3: comma-separated caller list
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
\NewDocumentEnvironment{int-interface}{mmm}%
{%before
  \phantomsection\label{iifprovided#1-#2}%
  % provided function interfaces
  \newpfuncollection{#1-provided-fun}%  
  \begin{collect} {#1-provided-fun}{}{}% 
  \item \hyperref[iifprovided#1-#2]{#1\_#2}
  \end{collect}%
  % 
  % needed function interfaces
  \def\callers{#3}
  \foreach \caller in \callers%
  {%
    \newnfuncollection{\caller-needed-fun}%  
    \begin{collect}{\caller-needed-fun}{}{}% 
    \item \hyperref[iifprovided#1-#2]{#1\_#2}%
    \end{collect}%
}%
%
\small     
\longtable[htbp]{>{\columncolor{IFcolor}}p{3.5cm}p{12cm}}\kill%\toprule
\endfirsthead
\multicolumn{2}{l}{\footnotesize\emph{Follows from previous page}} \\
\endhead
% normal foot
\multicolumn{2}{r}{\footnotesize\emph{Continue in the next page}} \\
\endfoot
% last foot
\bottomrule
\endlastfoot
%
% here the stationary contents
\toprule
Syntax & #1\_#2 \\
}%
{%
%after
Callers & #3 \\%
\endlongtable
}%
%
%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% environment for interfaces - variables
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% Usage: 
% param 1: Provider acronym
% param 2: name of variable
% param 3: comma-separated caller list, read access
% param 4: comma-separated caller list, write access
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
\NewDocumentEnvironment{int-interface-var}{mmmm}%
{%before
  \phantomsection\label{iifprovided#1-#2}%
%  provided function interfaces
  \newpvarcollection{#1-provided-var}%  
\begin{collect}{#1-provided-var}{}{}% 
\item \hyperref[iifprovided#1-#2]{#1\_#2}
\end{collect}%
%
%
% needed interfaces 
% two consecutive \foreach are used to decide whether writing R, W or R/W
% first loop search for every read caller in writecaller list; 
% if read caller is found in writecallers list, 
% a 'R/W' is appended; elsewhere, it is 'only' R. 
% Then similar thing is done starting from writecaller list:
% if actual writecaller is NOT found in readcaller list, it is marked only W;
% elsewhere nothing has to be done, because R/W has been already treated in 
% previous loop (RW)
\def\callersreadlist{#3}
\def\callerswritelist{#4}
% detecting RW or R
\foreach \readcaller in \callersreadlist
{
  \IfSubStr{\callerswritelist}{\readcaller}
  {
    \newnvarcollection{\readcaller-needed-var}%  
    \begin{collect}{\readcaller-needed-var}{}{}% 
    \item \hyperref[iifprovided#1-#2]{#1\_#2} [Read/Write]
    \end{collect}%
  }%
  % else%
  {%
    \newnvarcollection{\readcaller-needed-var}%  
    \begin{collect}{\readcaller-needed-var}{}{}% 
    \item \hyperref[iifprovided#1-#2]{#1\_#2} [Read only]
    \end{collect}%
  }%
}
% detecting W  
\foreach \writecaller in \callerswritelist
{
  \IfSubStr{\callersreadlist}{\writecaller}
  {
    % if found, nothing to do
  }%
  % else%
  {%
    \newnvarcollection{\writecaller-needed-var}%  
    \begin{collect}{\writecaller-needed-var}{}{}% 
    \item \hyperref[iifprovided#1-#2]{#1\_#2} [Write only]
    \end{collect}%
  }%
}   
%
% write longtable
\small    
  % didascalia ed etichetta
\longtable[htbp]{>{\columncolor{IFVcolor}}p{3.5cm}p{12cm}}\kill%\toprule
\endfirsthead
\multicolumn{2}{l}{\footnotesize\emph{Follows from previous page}} \\
\endhead
% piede normale
\multicolumn{2}{r}{\footnotesize\emph{Continue in the next page}} \\
\endfoot
% piede finale
\bottomrule
\endlastfoot
%
% here the stationary contents
\toprule
Syntax & #1\_#2 \\%
}%
{%
%after
% do the same search as before, to build list of read only, write only and read/write access modules
\def\callersreadlist{#3}%
\def\callerswritelist{#4}%
Accessed by: & %
\foreach\readcaller in \callersreadlist
{%
  \IfSubStr{\callerswritelist}{\readcaller}%
{%
    % if found
\readcaller{} \accessmode{rw}$\quad$%
}%
  % else%
{%
\readcaller{} \accessmode{r}$\quad$%
}%
}%
%  
%
\foreach\writecaller in \callerswritelist
{%
  \IfSubStr{\callersreadlist}{\writecaller}%
{%
}%
  % else%
{%
\writecaller{} \accessmode{w}$\quad$%
%
}%
}%
\\   
\endlongtable
}%
%
%
%
%
%
\newcommand{\accessmode}[1]{%
  (#1),
}%
%
\DeclareRobustCommand{\insertprovidedinterfaces}[1]{%
  \paragraph{Function interfaces}
  \IfSubStr{\pfuncollectionlist}{#1}{%
%    Collection '#1-provided-fun' exists
    \begin{itemize}
      \includecollection{#1-provided-fun}%
    \end{itemize}
  }{%   
    None.
  }%
  \paragraph{Variable interfaces}
  \IfSubStr{\pvarcollectionlist}{#1}{%
%    Collection '#1-provided-var' exists
    \begin{itemize}
      \includecollection{#1-provided-var}%
    \end{itemize}
  }{%   
    None.
  }%
}%
%
\DeclareRobustCommand{\insertneededinterfaces}[1]{%
  \paragraph{Function interfaces}
  \IfSubStr{\nfuncollectionlist}{#1}{%
%    Collection '#1-needed-fun' esists
    \begin{itemize}
      \includecollection{#1-needed-fun}%
    \end{itemize}
  }{%   
    None.
  }%
  \paragraph{Variable interfaces}
  \IfSubStr{\nvarcollectionlist}{#1}{%
%    Collection '#1-needed-var' esists
    \begin{itemize}
      \includecollection{#1-needed-var}%
    \end{itemize}
  }{%   
    None.
  }%
}%
%
\DeclareRobustCommand{\newpvarcollection}[1]{%
  \IfSubStr{\pvarcollectionlist}{#1}{%
  }{%
    \xdef\pvarcollectionlist{\pvarcollectionlist{} #1}
    \definecollection{#1}%
  }%
}%
%
\DeclareRobustCommand{\newnvarcollection}[1]{%
  \IfSubStr{\nvarcollectionlist}{#1}{%
  }{%
    \xdef\nvarcollectionlist{\nvarcollectionlist{} #1}
    \definecollection{#1}%
  }%
}%
%
\DeclareRobustCommand{\newpfuncollection}[1]{%
  \IfSubStr{\pfuncollectionlist}{#1}{%
  }{%
    \xdef\pfuncollectionlist{\pfuncollectionlist{} #1}
    \definecollection{#1}%    
  }%
}%
%
\DeclareRobustCommand{\newnfuncollection}[1]{%  
  \IfSubStr{\nfuncollectionlist}{#1}{%
  }{%
    \xdef\nfuncollectionlist{\nfuncollectionlist{} #1}
    \definecollection{#1}%
  }%
}%
%
\begin{document}
\section{Interfaces}
Here some software interfaces:
\begin{int-interface}{SUP}{eGetActualSystemStatus}{ICP}
  Parameters  & None                                        \\
  Return type & System status code. Codified value          \\
  Purpose     & Obtain actual system status from \emph{SUP} \\
\end{int-interface}
%
\begin{int-interface}{SUP}{eSetOverrideRequest()}{SMB}
  Parameters  & Request code: ENTER, EXIT                   \\
  Return type & Operation result. Codified value.           \\
  Purpose     & To set an override request to \emph{SUP}    \\
\end{int-interface}
%
\begin{int-interface-var}{HAL}{ausInputVoltageSamples}{SENS, I2C}{I2C, ICP}
  Type           & Buffer of 5 samples \\
  Purpose        & To store acquired input voltage samples\\
\end{int-interface-var}
%
\section{Modules description}
Some descriptive stuff\ldots

\subsection{SUP module}
Other descriptions\ldots

Here is a list of provided interfaces:
\insertprovidedinterfaces{SUP}

\subsection{HAL module}
Other descriptions\ldots

Here is a list of provided interfaces:
\insertprovidedinterfaces{HAL}
\end{document}
share|improve this question
add comment

2 Answers

up vote 2 down vote accepted

You can patch the commands of collect.sty that seem responsible for the error in your application. This shouldn't concern other uses of collect:

\makeatletter
\def\CE@ensure@opened#1{%
  \@ifundefined{ifCE@@#1@open}{%
    \PackageError{collect}{Collection `#1' has not been defined}{\@ehc}%
  }{%
    \csname ifCE@@#1@open\endcsname\else
    \immediate\expandafter\openout\csname CE@@#1@out\endcsname=\jobname.#1\relax
    \@ifundefined{CE@@#1@opentrue}{}{\global\csname CE@@#1@opentrue\endcsname}%
    \fi
  }%
}
\def\CE@ensure@closed#1{%   
  \@ifundefined{ifCE@@#1@open}{%
    \PackageError{collect}{Collection `#1' has not been defined}{\@ehc}%
  }{%
    \csname ifCE@@#1@open\endcsname
    \immediate\expandafter\closeout\csname CE@@#1@out\endcsname
    \@ifundefined{CE@@#1@openfalse}{}{\global\csname CE@@#1@openfalse\endcsname}%
    \fi
  }%   
}   
\makeatother

The code should go in the preamble; your MWE seems to run without errors.


The following seems a correct reimplementation of your minimal example (same document syntax) without using collect, but exploiting expl3.

\documentclass[a4paper, oneside, 10pt]{article}
\usepackage[english]{babel}
\usepackage[latin1]{inputenc}
\usepackage[T1]{fontenc}
\usepackage{lmodern}
\renewcommand*\familydefault{\sfdefault} 
\usepackage[table, svgnames]{xcolor}
\usepackage{booktabs}
\usepackage{xparse}
\usepackage{longtable}
\usepackage{tikz}%
\usepackage{hyperref}
%%
\colorlet{IFcolor}{Yellow!30!Blue!20}
\colorlet{IFVcolor}{Yellow!80!Blue!20}
%
% definitions of variables containing modules list, later used
% to avoid re-defining an already defined collection
% pfun -> provided functions
% nfun -> needed functions
% pvar -> provided variables
% nvar -> needed variables

\ExplSyntaxOn
\clist_new:N \g_cbe_pfuncollectionlist_clist
\clist_new:N \g_cbe_nfuncollectionlist_clist
\clist_new:N \g_cbe_pvarcollectionlist_clist
\clist_new:N \g_cbe_nvarcollectionlist_clist
%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% environment for interfaces - functions
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% Usage: 
% param 1: Provider acronym
% param 2: name of function including ()
% param 3: comma-separated caller list
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
\NewDocumentEnvironment{int-interface}{mmm}
 {
  \cbe_int_interface_start:nnn {#1}{#2}{#3}
 }
 {
  \cbe_int_interface_end:nnn {#1}{#2}{#3}
 }
\cs_new_protected:Npn \cbe_int_interface_start:nnn #1 #2 #3
 {
  \phantomsection\label{iifprovided#1-#2}%
  % provided function interfaces
  \cbe_newpfuncollection:n { #1 }%  
  \cbe_collect:nn {#1-provided-fun}{\item \hyperref[iifprovided#1-#2]{#1\_#2}}
  % needed function interfaces
  \clist_map_inline:nn { #3 }
   {
    \cbe_newnfuncollection:n { ##1 }%  
    \cbe_collect:nn {##1-needed-fun}{\item \hyperref[iifprovided#1-#2]{#1\_#2}}
   }
  %
  \small
  \longtable[htbp]{>{\columncolor{IFcolor}}p{3.5cm}p{12cm}}\kill%\toprule
  \endfirsthead
  \multicolumn{2}{l}{\footnotesize\emph{Follows~from~previous~page}} \\
  \endhead
  % normal foot
  \multicolumn{2}{r}{\footnotesize\emph{Continue~in~the~next~page}} \\
  \endfoot
  % last foot
  \bottomrule
  \endlastfoot
  % here the stationary contents
  \toprule
  Syntax & #1\_#2 \\
 }
\cs_new_protected:Npn \cbe_int_interface_end:nnn #1 #2 #3
 {
  Callers & #3 \\
  \endlongtable
  }
%
%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% environment for interfaces - variables
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% Usage: 
% param 1: Provider acronym
% param 2: name of variable
% param 3: comma-separated caller list, read access
% param 4: comma-separated caller list, write access
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
\NewDocumentEnvironment{int-interface-var}{mmmm}
 {
  \cbe_int_interface_var_start:nnnn {#1}{#2}{#3}{#4}
 }
 {
  \cbe_int_interface_var_end:nnnn {#1}{#2}{#3}{#4}
 }
\cs_new_protected:Npn \cbe_int_interface_var_start:nnnn #1 #2 #3 #4
 {
  \phantomsection\label{iifprovided#1-#2}
  % provided function interfaces
  \cbe_newpvarcollection:n { #1 }
  \cbe_collect:nn {#1-provided-var}{\item \hyperref[iifprovided#1-#2]{#1\_#2}}
  % needed interfaces 
  % two consecutive \foreach are used to decide whether writing R, W or R/W
  % first loop search for every read caller in writecaller list; 
  % if read caller is found in writecallers list, 
  % a 'R/W' is appended; elsewhere, it is 'only' R. 
  % Then similar thing is done starting from writecaller list:
  % if actual writecaller is NOT found in readcaller list, it is marked only W;
  % elsewhere nothing has to be done, because R/W has been already treated in 
  % previous loop (RW)
  % detecting RW or R
  \clist_map_inline:nn { #3 }
   {
    \clist_if_in:nnTF { #4 } { ##1 }
     {
      \cbe_newnvarcollection:n { ##1 }
      \cbe_collect:nn { ##1-needed-var }{ \item \hyperref[iifprovided#1-#2]{#1\_#2} [Read/Write] }
     }
     {
      \cbe_newnvarcollection:n { ##1 }
      \cbe_collect:nn { ##1-needed-var }{ \item \hyperref[iifprovided#1-#2]{#1\_#2} [Read~Only] }
     }
   }
  % detecting W  
  \clist_map_inline:nn { #4 }
   {
    \clist_if_in:nnF { #4 } { ##1 }
     {
      \cbe_newnvarcollection:n { ##1 }
      \cbe_collect:nn { ##1-needed-var }{\item \hyperref[iifprovided#1-#2]{#1\_#2} [Write~only]}
     }
   }
  % write longtable
  \small    
  % didascalia ed etichetta
  \longtable[htbp]{>{\columncolor{IFVcolor}}p{3.5cm}p{12cm}}\kill%\toprule
  \endfirsthead
  \multicolumn{2}{l}{\footnotesize\emph{Follows from previous page}} \\
  \endhead
  % piede normale
  \multicolumn{2}{r}{\footnotesize\emph{Continue in the next page}} \\
  \endfoot
  % piede finale
  \bottomrule
  \endlastfoot
  %
  % here the stationary contents
  \toprule
  Syntax & #1\_#2 \\
 }
\cs_new_protected:Npn \cbe_int_interface_var_end:nnnn #1 #2 #3 #4
 {
  % do the same search as before, to build list of read only, write only and read/write access modules
  Accessed~by: & 
  \clist_map_inline:nn { #3 }
   {
    \clist_if_in:nnTF { #4 } { ##1 }
     {
      ##1 ~ \cbe_accessmode:n { rw } \quad
     }
     {
      ##1 ~ \cbe_accessmode:n { r } \quad
     }
   }
  \clist_map_inline:nn { #4 }
   {
    \clist_if_in:nnF { #3 } { ##1 }
     {
      ##1 ~ \cbe_accessmode:n { w } \quad
     }
   }
  \\   
  \endlongtable
 }
%
\cs_new_protected:Npn \cbe_accessmode:n #1
 {
  (#1),
 }
%
\NewDocumentCommand{\insertprovidedinterfaces}{m}
 {
  \paragraph{Function~interfaces}
  \clist_if_in:NnTF \g_cbe_pfuncollectionlist_clist { #1 }
   {
    % Collection '#1-provided-fun' exists
    \begin{itemize}
      \cbe_includecollection:n {#1-provided-fun}
    \end{itemize}
   }
   {
    None.
   }
  \paragraph{Variable~interfaces}
  \clist_if_in:NnTF \g_cbe_pvarcollectionlist_clist { #1 }
   {
    % Collection '#1-provided-var' exists
    \begin{itemize}
      \cbe_includecollection:n {#1-provided-var}
    \end{itemize}
   }
   {
    None.
    }
 }
%
\NewDocumentCommand{\insertneededinterfaces}{m}
 {
  \paragraph{Function interfaces}
  \clist_if_in:NnTF \g_cbe_nfuncollectionlist_clist { #1 }
   {
    % Collection '#1-needed-fun' esists
    \begin{itemize}
      \cbe_includecollection:n {#1-needed-fun}
    \end{itemize}
   }
   {
    None.
   }
  \paragraph{Variable~interfaces}
  \clist_if_in:NnTF \g_cbe_nvarcollectionlist_clist { #1 }
   {
    % Collection '#1-needed-var' esists
    \begin{itemize}
      \cbe_includecollection:n {#1-needed-var}%
    \end{itemize}
   }
   {
    None.
   }
 }
%
\cs_new_protected:Npn \cbe_newpvarcollection:n #1
 {
  \clist_if_in:NnF \g_cbe_pvarcollectionlist_clist { #1 }
   {
    \clist_gput_right:Nn \g_cbe_pvarcollectionlist_clist { #1 }
   }
  \cbe_newcollection:nn { #1 } { provided-var }
 }
%
\cs_new_protected:Npn \cbe_newnvarcollection:n #1
 {
  \clist_if_in:NnF \g_cbe_nvarcollectionlist_clist { #1 }
   {
    \clist_gput_right:Nn \g_cbe_nvarcollectionlist_clist { #1 }
   }
  \cbe_newcollection:nn { #1 } { needed-var }
 }
%
\cs_new_protected:Npn \cbe_newpfuncollection:n #1
 {
  \clist_if_in:NnF \g_cbe_pfuncollectionlist_clist { #1 }
   {
    \clist_gput_right:Nn \g_cbe_pfuncollectionlist_clist { #1 }
   }
 \cbe_newcollection:nn { #1 } { provided-fun }
 }
%
\cs_new_protected:Npn \cbe_newnfuncollection:n #1
 {
  \clist_if_in:NnF \g_cbe_nfuncollectionlist_clist { #1 }
   {
    \clist_gput_right:Nn \g_cbe_nfuncollectionlist_clist { #1 }
   }
  \cbe_newcollection:nn { #1 } { needed-fun }
 }

\cs_new_protected:Npn \cbe_newcollection:nn #1 #2
 {
  \tl_if_exist:cF { g_cbe_collection_#1-#2_tl }
   { \tl_new:c { g_cbe_collection_#1-#2_tl } }
 }

\cs_new_protected:Npn \cbe_collect:nn #1 #2
 {
  \tl_gput_right:cn { g_cbe_collection_#1_tl } { #2 }
 }

\cs_new_protected:Npn \cbe_includecollection:n #1
 {
  \tl_use:c { g_cbe_collection_#1_tl }
 }
\ExplSyntaxOff

\begin{document}
\section{Interfaces}
Here some software interfaces:
\begin{int-interface}{SUP}{eGetActualSystemStatus}{ICP}
  Parameters  & None                                        \\
  Return type & System status code. Codified value          \\
  Purpose     & Obtain actual system status from \emph{SUP} \\
\end{int-interface}
%
\begin{int-interface}{SUP}{eSetOverrideRequest()}{SMB}
  Parameters  & Request code: ENTER, EXIT                   \\
  Return type & Operation result. Codified value.           \\
  Purpose     & To set an override request to \emph{SUP}    \\
\end{int-interface}
%
\begin{int-interface-var}{HAL}{ausInputVoltageSamples}{SENS, I2C}{I2C, ICP}
  Type           & Buffer of 5 samples \\
  Purpose        & To store acquired input voltage samples\\
\end{int-interface-var}
%
\section{Modules description}
Some descriptive stuff\ldots

\subsection{SUP module}
Other descriptions\ldots

Here is a list of provided interfaces:
\insertprovidedinterfaces{SUP}

\subsection{HAL module}
Other descriptions\ldots

Here is a list of provided interfaces:
\insertprovidedinterfaces{HAL}
\end{document}

I maintain four clist variables, for checking whether the interfaces already exist and each function and variable description is added to a token list variable called \g_cbe_<interface>-provided-fun_tl, \g_cbe_<interface>-needed-fun_tl, \g_cbe_<interface>-provided-var_tl, \g_cbe_<interface>-needed-var_tl, that is then used when \insertprovidedinterfaces{<interface>} is called.

At least for the example I get the same result as yours.

enter image description here

share|improve this answer
    
I've put your code in my package, it works perfectly even on the full document. Maybe this can be included (don't know how) in an update of the collect package? I've contacted the author, but unfortunately he seems no more involved in its maintenance... –  cbe Oct 5 '12 at 19:39
    
@cbe I believe it's the wrong tool for the job. –  egreg Oct 5 '12 at 19:54
    
Can you suggest a better way for doing that? I was in hurry when searching a package to do the work, so I initially stopped my search at the first working solution... –  cbe Oct 5 '12 at 19:59
    
@cbe I've added a reimplementation using expl3 –  egreg Oct 5 '12 at 20:22
    
Just tested on the whole document, runs perfectly. I'm going to study expl3 right now :) –  cbe Oct 5 '12 at 20:49
show 2 more comments

It is a far from minimal example and I don't know what the intended output should look like, but

\DeclareRobustCommand{\insertprovidedinterfaces}[1]{%
\begingroup
\let\oldopenin\openin
\def\openin{\def\zzzz{}\oldopenin}

  \paragraph{Function interfaces}
  \IfSubStr{\pfuncollectionlist}{#1}{%
%    Collection '#1-provided-fun' exists
    \begin{itemize}
      \includecollection{#1-provided-fun}%
    \end{itemize}
  }{%   
    None.
  }%
  \paragraph{Variable interfaces}
  \IfSubStr{\pvarcollectionlist}{#1}{%
%    Collection '#1-provided-var' exists
    \begin{itemize}
      \includecollection{#1-provided-var}%
    \end{itemize}
  }{%   
    None.
  }%
\endgroup}%

makes the error go away. Probably it is just masking a mis-use of \openin elsewhere in the code.

share|improve this answer
    
Your solutions works on the (not) MWE (sorry for that), but, on the full document, pdfLaTeX freezes after a while, and seem waiting for something. I've managed to get it work by adding \let\openin\oldopenin before \endgroup, restoring the original behaviour after my command has been processed. Thanks! –  cbe Oct 5 '12 at 14:24
    
With \tracingall I get that \CE@@SUP-provided-fun@openfalse is undefined, so \csname CE...\endcsname changes it into \relax; hence TeX sees \global\relax\fi\@input; \fi disappears and \@input is expanded: it starts with \openin. So the problem is in the undefined conditional \ifCE@@SUP-... that seems due to a misuse of collect macros. –  egreg Oct 5 '12 at 14:43
    
@egreg yes that's about where I gave up too:-) –  David Carlisle Oct 5 '12 at 14:55
    
The problem seems to be in the fact that \definecollection is called inside an environment. –  egreg Oct 5 '12 at 15:01
    
@egreg: \definecollection is called from an environment in which I check if a collection already exists before trying to create it. My intention was to allow users to write new interfaces without worrying if collection that will contain its name was already defined or not. Is there something wrong in my code that I can't see? –  cbe Oct 5 '12 at 15:57
show 1 more comment

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.