m4 does not obey expansion? - preprocessor

I use m4 for a little text preprocessing here, and it behaves in a way I don't understand.
This is the portion in question:
ifdef(`TEST',
define(`O_EXT', `.obj'),
define(`O_EXT', `.o'))
This macro will always be expanded to .o, regardless whether TEST is defined (m4 -DTEST) or not.
What am I doing wrong?

You're not quoting the other arguments to ifdef. Try this:
ifdef(`TEST', `define(`O_EXT', `.obj')', `define(`O_EXT', `.o')')

Related

Conditional compilation/interpretation using m4

I would like to use m4 as a preprocessor for a couple of different scripting languages that lack this facility.
In particular, I need to emulate the C preprocessor (cpp) functionality of conditional code inclusion:
#if something
some
long
code
block
#else
alternate
code
block
#if something-else
do
more
stuff
#endif
#endif
m4's ifelse() does not particularly lend itself to long code blocks, so it seems I essentially need to write m4 macros to emulate this, by testing the condition and then using divert to include or exclude blocks as appropriate.
The tricky part will be keeping track of nesting levels; as far as I can tell, I will have to implement my own stack within m4 to do this. This seems conceptually straightforward, and I'm sure with a day or two of hacking I can have a working system.
But it feels like reinventing the wheel — I surely can't be the first person with this need. Existing, tested, robust solutions are surely better than whatever I can hack together as an m4 rank beginner.
Are there common m4 idioms for this? Is there existing open-source m4 code to do this? Poking around in search engines didn't turn up anything useful.
(Using cpp itself won't work for reasons given in cpp's own documentation: "It will choke on input which does not obey C's lexical rules." It seems gpp has this functionality out of the box, so using that might make more sense, but I prefer the ubiquity of m4 if it's not too painful to make m4 do this.)
I was also looking for this, and ended up writing my own. Here is a link to the code on my wiki:
http://www.eugeneweb.com/wiki/Sites/M4Macros
I defined the names without the #'s eg. IF, ELSE, ENDIF, etc... Also M4 requires parens to hold the arguments where CPP (Mostly) does not. I also added a selective invoke to protect macros with side effects from invocation in an unselected block.
Ciao.

Check multiple conditions at once using m4 preprocessor

There is any m4 syntax that is equivalent to this C preprocessor one?
#if defined A || defined B
do something
#endif
The short answer is no.
The long answer:
Checking if macros are defined
define(`defined', `ifelse($1()$1, `$1()$1', ``0'', ``1'')')
ifelse(eval(defined(`A') || defined(`B')),
1,
``At least one is defined'',
``Neither are defined'')
There are no sensible ways to check for a defined macro in m4, so you would have to resort to hacks like the above.
How it works
ifelse checks for equality of two strings. In the defined macro, I've expanded the macro in $1 twice (once as $1(), once as $1). I'm comparing it against $1()$1 as a string, so if it doesn't expand then it will compare true. The reason for specifying the macros in two different ways is because A could be defined as ``A'' or ``A()'' which would otherwise cause false negatives when using this method to check whether or not it is defined.
I'm then using that defined macro within an eval to throw the || logic on top.
Caveats
If you use the word defined in your document already, you might want to give the macro a different name.
The defined macro will not work on macros defined to expand to unquoted syntactic markers like (, ,, or ).
If the macro to be checked is infinitely recursive, the defined check will also never return. (Essentially, realize that a hack like this is still actually executing the macro.)
Though the last 2 points there are something you'd expect from any ifelse check on a macro, it might not be intuitive to expect it from a macro purporting to check for whether another macro is defined.
A better way
I would much rather suggest that you define the variables with some default value first, and just avoid the problem of checking whether it is defined or not altogether.
This is much easier to do:
# Define this right off the bat:
define(`A', ``0'')
# Maybe later this line will come up...
# Quotes around the A are mandatory
define(`A', ``1'')
# Then soon after that, you can check:
ifelse(A, `0', , ``hey, A is nonzero!'')

LaTeX to "freeform" converter

I would like to develop a converter that will accept math written in "freeform" or something like Wolfram Alpha would accept. For example: 2*x+(7+y)/(z^2) will be transformed to 2\cdot x+\frac{7+y}{z^{2}} (please ignore any syntax mistakes I might have made here) and vice versa. I was wondering if there exists a LaTeX library for C++/Java that parses and/or holds LaTeX expression in memory. If so, please share.
If not, how would you go about writing something like this? Is it okay to use normal Java/C++ code for this or should I use something like lex?
Yes, it is absolutely OK to write the parser for ‘freeform’ in Flex/Bison, in fact I’d recommend against using TeX, as that language was not written for parsing. I even remember having done exactly that (‘freeform’ to LaTeX) as an exercise with Flex and Bison and Kimwitu++, which allowed to perform arbitrary transformations before output. Note that you dropped the parentheses of your original formula. This might of might not be what you want in the general case.
For the other way round, the comments already mentioned that it’s nearly impossible to do in the general case. For restricted cases, Bison is good enough.

Can I make a LaTeX macro 'return' a filename?

I'm writing my thesis/dissertation and since its an on-going work I don't always have the actual images ready for the figures I put into my document, but for various reasons want to automatically have it substitute a dummy figure in place when the included graphics file doesn't exist. E.g. I can do something like \includegraphics[width=8cm]{\chapdir/figures/fluxcapacitor} (where \chapdir is a macro for my 'current' chapter directory, e.g. \def\chapdir{./ch_timetravel} and if there's no ./ch_timetravel/figures/fluxcapacitor.jpg it'll insert ./commands/dummy.jpg instead.
I've structured my macros (perhaps naïvely?) so that I have a macro (\figFileOrDummy) that determines the appropriate file to include by checking if the argument provided to it exists, so that I can call \includegraphics[properties]{\figFileOrDummy{\chapdir/figures/fluxcapacitor}}. Except I'm getting various errors depending on how I try to call this, which seem to suggest that I'm approaching the problem in a fundamentally flawed way as far as 'good LaTeX programming' goes.
Here's the macro to check if the file exists (and 'return' either filename or the dummy filename):
\newcommand{\figFileOrDummy}[1]{%
% Figure base name (no extension) to be used if the file exists
\def\fodname{#1}%
\def\dummyfig{commands/dummy}%
% Check if output is PS (.EPS) or PDF (.JPG/.PDF/.PNG/...) figures
\ifx\pdfoutput\undefined%
% EPS figures only
\IfFileExists{\fodname.eps}{}{\def\fodname{\dummyfig}}%
\else%
% Check existence of various extensions: PDF, TIF, TIFF, JPG, JPEG, PNG, MPS
\def\figtest{0}% flag below compared to this value
\IfFileExists{\fodname.pdf}{\def\figfilenamefound{1}}{\def\figfilenamefound{0}}%
\IfFileExists{\fodname.jpg}{\def\figfilenamefound{1}}{}%
\IfFileExists{\fodname.png}{\def\figfilenamefound{1}}{}%
% and so on...
% If no files found matching the filename (flag is 0) then use the dummy figure
\ifx\figfilenamefound\figtest%
\def\fodname{\dummyfig}%
\fi%
\fi%
% 'return' the filename
\fodname%
}%
Alternatively, here's a much simpler version which seems to have similar problems:
\newcommand{\figFileOrDummy}[1]{%
\def\dummyfig{commands/dummy}%
\dummyfig%
}
The \def commands seems to be processed after the expansion of the macro they're trying to define, so it ends up being \def {commands/dummy}... (note the space after \def) and obviously complains.
Also it seems to treat the literal contents of the macro as the filename for \includegraphics, rather than resolving/expanding it first, so complains that the file '\def {commands/dummy}... .png' doesn't exist..
I've tried also doing something like
\edef\figfilename{\figFileOrDummy{\chapdir/figures/fluxcapacitor}} to try to force it to make \figfilename hold just the value rather than the full macro, but I get an Undefined control sequence error complaining the variables I'm trying to \def in the \figFileOrDummy macro are undefined.
So my question is either
How do I make this macro expand properly?; or
If this is the wrong way of structuring my macros, how should I actually structure such a macro, in order to be able to insert dummy/real figures automatically?; or
Is there a package that already handles this type of thing nicely that I've overlooked?
I feel like I'm missing something pretty fundamental here...
I think the point is that \expandafter is only interested in its arguments as a string representing a filename, so doesn't evaluate it — macro languages are lazy! Try \expandafter {\includegraphics[width=8cm]}{\chapdir/figures/fluxcapacitor}.
Two points of style:
You don't need to put % at the end of a line to stop spurious whitespace if the line ends with a control sequence: the control sequence gobbles up all following whitespace, including the end of line. This makes the code much more readable, to my taste. Note that, in particular, to Tex's "mouth" both \def\newcs{abc} and \def \newcs {abc} are identical: they are exactly the same sequence of tokens.
I dropped the code around \figtest: you get better error reporting -always at a premium with Tex- if you use either \newif primitive (create new test with \newif\figexists, set/reset with \figexiststrue, \figexistsfalse, and test with \iffigexists...) or the Latex ifthenelse package (to keep with orthodoxy).
Cleaned-up code
I first thought the problem lay elsewhere, so wrote something prettier:
\def\dummypath{commands/dummy}%
\ifx\pdfoutput\undefined
\def\figFileOrDummy#1{\IfFileExists
{#1.eps}{#1}\dummypath}
\else
\def\figFileOrDummy#1{\IfFileExists
{#1.pdf}{#1}{\IfFileExists
{#1.jpg}{#1}{\IfFileExists
{#1.png}{#1}\dummypath}}} %or have more graphics types, if you like.
\fi
Alright, so I've found a possible answer to #2, by restructuring the way the macros work (and sort of using some suggestions from Charles Stewart's answer — I'll admit I don't like the 'look' of what seems to be widely considered good LaTeX code, I'm perhaps too ingrained in my C/C++ ways to be a real LaTeX programmer).
Anyway, my answer...
Instead of trying to produce the file name in a macro to pass to the \includegraphics macro, make a macro that wraps \includegraphics and passes it the real or dummy file name. This seems to avoid passing (as an argument) a long script/macro, though I don't see any good reason why it should have to be written this way. But it does work...
% Dummy figure file
\def\dummyfigure{commands/dummy}%
% Includegraphics wrapper macro to include either dummy or real figure
\ifx\pdfoutput\undefined
\newcommand{\incgfx}[2]{%
\def\testfile{\chapdir/fig/#2}%
\IfFileExists{\testfile.eps}%
{\includegraphics[#1]{\testfile}}% test file found
{\includegraphics[#1]{\dummyfigure}}% test file not found
}
\else
\newcommand{\incgfx}[2]{%
\def\figfilename{\dummyfigure}
\def\testfile{\chapdir/fig/#2}
\IfFileExists{\testfile.jpg}{\def\figfilename{\testfile}}{}
\IfFileExists{\testfile.png}{\def\figfilename{\testfile}}{}
\IfFileExists{\testfile.pdf}{\def\figfilename{\testfile}}{}
\IfFileExists{\testfile.jpeg}{\def\figfilename{\testfile}}{}
\IfFileExists{\testfile.tif}{\def\figfilename{\testfile}}{}
\IfFileExists{\testfile.tiff}{\def\figfilename{\testfile}}{}
\includegraphics[#1]{\figfilename}
}
\fi
This allows one to use it as intended:
\begin{figure}
\begin{center}
\incgfx{height=3cm}{\chapdir/fig/fluxcapacitor}
\caption{...}\label{fig:...}
\end{center}
\end{figure}
Again, I'd like to think there's a way to make the original idea work rather than having to make a wrapper for existing functions, but this will do for now...
Answer to #3: For this purpose, I find very useful the todonotes package. It does not provide the level of automation that your code is aiming to offer, but it has a very nice \missingfigure command that lets you put a dummy box for, you guess it, a missing figure.

Transform a tex source so that all macros are replaced by their definition

Is it possible to see the output of the TeX ‘pre-processor’, i. e. the intermediate step before the actual output is done but with all user-defined macros replaced and only a subset of TeX primitives left?
Or is there no such intermediate step?
Write
\edef\xxx{Any text with any commands. For example, $\phantom x$.}
And then for output in the log-file
\show\xxx
or for output in your document
\meaning\xxx
There is no "pre-processor" in TeX. The replacement text for any control sequence at any stage can vary (this is used for a lot of things!). For example
\def\demo{\def\demo{cde}}
\demo
will first define \demo in one way and then change it. In the same way, you can redirect TeX primitives. For example, the LaTeX kernel moves \input to an internal position and alters it. A simplified version:
\let\##input\input
\def\input#1{\##input#1 }
Try the Selective Macro Expander.
TeX has a lot of difference tracing tools built in, including tracing macro expansion. This only traces live macros as they are actually expanded, but it's still quite useful. Full details in The TeXbook and probably elsewhere.
When I'm trying to debug a macro problem I generally just use the big hammer:
\tracingall\tracingonline
then I dig in the output or the .log file for what I want to know.
There's a lot of discussion of this issue on this question at tex.SE, and this question. But I'll take the opportunity to note that the best answer (IMO) is to use the de-macro program, which is a python script that comes with TeXLive. It's quite capable, and can handle arguments as well as simple replacements.
To use it, you move the macros that you want expanded into a <something>-private.sty file, and include it into your document with \usepackage{<something>-private}, then run de-macro <mydocument>. It spits out <mydocument>-clean.tex, which is the same as your original, but with your private macros replaced by their more basic things.

Resources