7

I would like to extract a value from a .h head (C language) and use this value as input to LaTeX.

As an example, consider defines.h:

#define MEB_COM_PACKET_ID 0x01

using this value on a table of a .tex document main.tex:

\begin{table}[ht!]
\begin{tabularx}{0.5\textwidth}{l  X}
    Value & Description \\
    \hline \hline 
    **MEB_COM_PACKET_ID** & balblabla blabla \\
\end{tabularx} 
\end{table}

where MEB_COM_PACKET_ID would be updated with 0x01.

Werner
  • 603,163

4 Answers4

5

The following example uses the C preprocessor to get the correct values of the defines in a format, which can be easily read by LaTeX.

The file defines_tex.c includes the needed headers surrounded by \iffalse and \fi. The preprocessor includes the header and passes the TeX code through, because the TeX code does not contain preprocessor directives. Then TeX code follows, which defines the needed macros with the defines as values, e.g.:

\newcommand*{\MebComPacketId}{MEB_COMP_PACKET_ID}

The this C file is run through the C preprocessor:

gcc -E -P defines_tex.c >defines_tex.tex

With enabled shell escape, the C preprocessor can be called from within LaTeX or it is called before the LaTeX run.

The generatedTeX file is included as usual in LaTeX:

\input{defines_tex}

The header C code is ignored because of wrapping it in \iffalse and \fi. (The C code should not accidently contain unmatched TeX conditionals or unmatched braces.)

Full example:

\documentclass{article}
\usepackage{filecontents}
\usepackage{booktabs}
\usepackage{tabularx}

\begin{filecontents*}{defines_tex.c}
\iffalse
#include <stdio.h>
#include "defines.h"
\fi
\newcommand*{\MebComPacketId}{MEB_COM_PACKET_ID}
#ifdef MEB_COM_PACKET_NAME
\newcommand*{\MebComPacketName}{MEB_COM_PACKET_NAME}
#else
\newcommand*{\MebComPacketName}{unknown}
#endif
\newcommand*{\SeekCur}{SEEK_CUR}% from stdio.h
\end{filecontents*}
% Call of C preprocessor, when shell escape is enabled
\immediate\write18{gcc -E -P defines_tex.c >defines_tex.tex}
% Load the definition file
\input{defines_tex}

\begin{document}
% Use of the defined values
\begin{tabular}{ll}
  \toprule
  Variable & Value \\
  \midrule
  \verb|MEB_COM_PACKET_ID|   & \MebComPacketId\\
  \verb|MEB_COM_PACKET_NAME| & \MebComPacketName\\
  \verb|SEEK_CUR|            & \SeekCur\\
  \bottomrule
\end{tabular}
\end{document}

Result

Heiko Oberdiek
  • 271,626
3

This requires slightly altered syntax of \?{MEB_COM_PACKET_ID} in the table.

\documentclass{article}
\usepackage{readarray,filecontents,ifthen,tabularx}

\begin{filecontents*}{defines.h}
#define MEB_COM_PACKET_ID 0x01
#define OTHER_ID 0x07
\end{filecontents*}

\newcommand\?[1]{\csname#1\endcsname}
\newcounter{defsindex}
\catcode`#=12 %
\def\ReadTheDefs{%
  \readdef{defines.h}{\Definitions}
  \readArrayij{\Definitions}{Defs}{3}
  \whiledo{\value{defsindex} < \DefsROWS}{
    \stepcounter{defsindex}%
    \def\DEFROW{\arabic{defsindex}}%
    \ifthenelse{\equal{\arrayij{Defs}{\DEFROW}{1}}{#define}}{%
    \expandafter\xdef\csname\arrayij{Defs}{\DEFROW}{2}\endcsname{%
      \arrayij{Defs}{\DEFROW}{3}}}{}%
  }%
}
\catcode`#=6 
\begin{document}
\begin{table}[ht!]
\catcode`#=12 \ReadTheDefs\catcode`#=6 %
\begin{tabularx}{0.5\textwidth}{l  X}
    Value & Description \\
    \hline \hline 
    \?{MEB_COM_PACKET_ID} & balblabla blabla \\
    \hline \hline 
    \?{OTHER_ID} & more stuff \\
\end{tabularx} 
\end{table}
\end{document}

enter image description here

2

You can use the following setup to extract the content from defines.h:

  1. Capture the file contents of defines.h inside a macro (using catchfile;

  2. Use TeX's parameter text definitions to extract the appropriate values. This works like a pattern-recognition definition, extracting only what matches the pattern.

The following example does the above:

enter image description here

\documentclass{article}

\usepackage{catchfile,filecontents}

% Create a dummy defines.h
\begin{filecontents*}{defines.h}
#define MEB_COM_PACKET_ID_NAME abc
#define MEB_COM_PACKET_ID 0x01
#define MEB_COM_PACKET_TYPE def
\end{filecontents*}

\def\extractMEBNAME#1 MEB_COM_PACKET_ID_NAME #2 #3\@nil{#2}
\def\extractMEBID#1 MEB_COM_PACKET_ID #2 #3\@nil{#2}
\def\extractMEBTYPE#1 MEB_COM_PACKET_TYPE #2 #3\@nil{#2}

\begin{document}

\CatchFileDef{\defines}{defines.h}{\catcode`\#=11}% Capture defines.h into \defines (making # act like a regular letter)

\noindent
\begin{tabular}{l l}
    Value & Description \\
    \hline 
    \verb|MEB_COM_PACKET_ID_NAME| & \expandafter\extractMEBNAME\defines\@nil \\% Extract MEB_COM_PACKET_ID_NAME value
    \verb|MEB_COM_PACKET_ID| & \expandafter\extractMEBID\defines\@nil \\% Extract MEB_COM_PACKET_ID value
    \verb|MEB_COM_PACKET_TYPE| & \expandafter\extractMEBTYPE\defines\@nil \\% Extract MEB_COM_PACKET_TYPE value
\end{tabular} 

\end{document}

Note that if the pattern used in (2) above doesn't exist, an error will occur.

Werner
  • 603,163
2

A variant of Werner's and Steven's answers, under the assumption that defines.h only contains statements of the form

#define VAR value

and that value doesn't contain @ (the character can be changed).

Here's the example file

% Create a dummy defines.h
\begin{filecontents*}{defines.h}
#define MEB_COM_PACKET_ID_NAME abc
#define MEB_COM_PACKET_ID 0x01
#define MEB_COM_PACKET_TYPE def
\end{filecontents*}

\documentclass{article}

\usepackage{catchfile}

\begingroup
\CatchFileDef{\defines}{defines.h}{\catcode`\#=0 \endlinechar=`@ }
\def\define #1 #2@{\expandafter\gdef\csname#1\endcsname{#2}}
\defines
\endgroup
\newcommand{\?}[1]{%
  \ifcsname#1\endcsname
    \csname#1\endcsname
  \else
    UNDEFINED VAR
  \fi
}

\begin{document}

\begin{tabular}{l l}
Value & Description \\
\hline 
\verb|MEB_COM_PACKET_ID_NAME| & \?{MEB_COM_PACKET_ID_NAME} \\
\verb|MEB_COM_PACKET_ID| & \?{MEB_COM_PACKET_ID} \\
\verb|MEB_COM_PACKET_TYPE| & \?{MEB_COM_PACKET_TYPE} \\
\verb|WHATEVER| & \?{WHATEVER} \\
\end{tabular} 

\end{document}

enter image description here

egreg
  • 1,121,712