11

In C, I can write #pragma once as a preprocessor directive at the top of a header file, which tells any compiler that supports it to include the file a maximum of one time per compilation cycle, regardless of how many times I #include that header file in the other source files. It is a common alternative to #ifndef/#define/#endif include guards, despite not being an officially documented/supported part of the standard.

La(TeX) has several facilities for so-called "include guards", many of which are outlined in the answers to Conditional typesetting / build.

My question is: Does there exist (or is there a possibility of) a construct in (La)TeX analogous to #pragma once in the C language; that is, a directive set on one line of a file which causes that file to be input only one time during the compilation?

MWE for Testing:

\documentclass{article}
\usepackage{filecontents}

\begin{filecontents*}{mydefs.tex}
%<-- insert magic *#pragma once*-like line here to prevent errors
\newcommand{\foo}{foo}
\newcommand{\baz}{baz}
\end{filecontents*}

\begin{document}
\input{mydefs}
\input{mydefs}
\foo\ \baz\ test.
\end{document}

Note:

You might say to just use \providecommand and be done with it, which is a valid answer. But I would like to know if what I've proposed is possible with (La)TeX, for science!

Paul Gessler
  • 29,607
  • You could use a flag, and wrap the \input command to test first. – Ethan Bolker Aug 06 '14 at 16:15
  • 3
    You know that's what \usepackage does, I suppose? If you want to do things 'by hand' it's normal to do \csname myresevedname\endcsname\let\myreservedname\endinput (if it's not been defined, the \csname construct will do nothing important, and on a second pass it will be set up equal to \endinput). – Joseph Wright Aug 06 '14 at 16:23
  • 2
    Well, you can use gpp on LaTeX files. – Raphael Aug 06 '14 at 20:58

2 Answers2

9

May be you needn't to deal with the name of the file or with another special identifier at the start ot such file. If I understand your question, you need only simply type \pragmaonce at the start of the file. I've looked to the LaTeX internals and I've found that: if the \input is followed by {, i. e. \input{filename}, then the \@iinput{filename} macro is processed. Thus I redefined this macro:

\documentclass{article}
\usepackage{filecontents}

\makeatletter
\let\pragma@iinput=\@iinput
\def\@iinput#1{\xdef\@pragmafile{#1}\pragma@iinput{#1}}
\def\@pragmafile{default}
\def\pragmaonce{%
   \csname pragma@\@pragmafile\endcsname
   \global\expandafter\let \csname pragma@\@pragmafile\endcsname = \endinput
}
\makeatother

\begin{filecontents*}{mydefs.tex}
\pragmaonce %<-- insert magic *#pragma once*-like line here to prevent errors
\newcommand{\foo}{foo}
\newcommand{\baz}{baz}
\end{filecontents*}

\begin{document}
\input{mydefs}
\input{mydefs}
\foo\ \baz\ test.
\end{document}

Of course, you have to respect the discipline and to type the \input only with braces around filename.

wipet
  • 74,238
5

If you load mydefs with \usepackage, giving it the .sty extension, LaTeX will load it only once. But it will not be available after \begin{document}.

The analog of #pragma once could be

\ifcsname mydefs.tex\endcsname
  \expandafter\endinput
\fi
\expandafter\gdef\csname mydefs.tex\endcsname{loaded}

<code in mydefs.tex>
egreg
  • 1,121,712