7

Since \newsavebox{\name} assigns the box register number to \name, there are probably a maximum of 256 boxes available. Is there a way to release a \savebox after you are through with it?

  • 3
    You can set the contents of the box as many times as you want. – egreg Jun 16 '14 at 15:29
  • 3
    Also most people use an etex based format in which case there are 32768 rather than 256 box registers – David Carlisle Jun 16 '14 at 15:34
  • 1
    You have the temporary boxes available to you: \setbox0=\hbox{...} then \box0 to output it. Depending on your application, these could serve and be constantly reused. – Steven B. Segletes Jun 16 '14 at 15:45
  • @Steven B. Segletes - How many are temporary and how many are reserved by \newsavebox? My guess would be that box0 - box25 are temporary. – John Kormylo Jun 18 '14 at 20:08
  • @JohnKormylo I've always assumed that all temporary boxes are subject to destruction if left unattended long enough. In fact, Knuth points out that the use of \boxn causes \boxn to become void (i.e., it loses its contents). So I don't know the answer to your question, sad to say. I did just learn that \copyn uses box n without destroying it. Interesting... – Steven B. Segletes Jun 18 '14 at 20:36
8

The normal model is to allocate a box once (before the document starts) and use it multiple times in whatever macro is being defined, so the limit is not usually a problem, however all modern distributions use an etex based format for LaTeX in which case there are 32768 registers available (although you need \usepackage{etex} to declare that to latex and to use an allocation scheme that knows about the registers.

  • 4
    We should integrate etex into the kernel, like I said :-) – Joseph Wright Jun 16 '14 at 16:09
  • 1
    @JosephWright I could hear you as I posted the above:-) – David Carlisle Jun 16 '14 at 16:13
  • I understand the current thinking in computer science is to deliberately make programs as bloated and slow as possible so as to force people to buy new computers. ;-) – John Kormylo Jun 17 '14 at 12:56
7

As mentioned by others, LaTeX doesn't provide a way to free up unused registers. It's bit more difficult that your example code suggests since you could add `holes' to the list of allocated registers that you'd need to fill; keeping track of them would be awkward or slow.

If you find yourself needing to use many many registers that you would like to free up, etex.sty has `local' register allocation under the macros

  • \loccount
  • \locdimen
  • \locskip
  • \locmuskip
  • \locbox
  • \loctoks
  • \locmarks

An example is shown following; you can see that the same box gets allocated twice under different names.

\documentclass[a4paper]{article}
\usepackage{etex}
\begin{document}

\begingroup
\locbox\textbox
\savebox\textbox{this is box \the\textbox: some text}
\fbox{\usebox\textbox}
\endgroup

\begingroup
\locbox\textboxB
\savebox\textboxB{this is box \the\textboxB: some more text}
\fbox{\usebox\textboxB}
\endgroup

\end{document}

To be effective you'll need grouping, but if you have such a prodigious need for save boxes then you'll probably be grouping at some level anyway.

  • We've steered away from offering local allocators in expl3 because of inconsistencies with edge cases with token lists (specifically, if you globally assign to a local register, it still disappears, but if you globally assign to a local macro, it stays). But if we assumed that all \g_ tls must be allocated globally and all \l_ must be allocated locally, we would be okay (and this is also recommended in TeX for performance reasons). So with sufficient interest this matter could probably be revived again... – Will Robertson Jun 17 '14 at 3:21
  • If you remember, the other problem was that as TeX's group model requires explicit groups, it looked as if creating local registers could lead to a lot of confusion. – Joseph Wright Jun 17 '14 at 5:53
  • @JosephWright — Looks like I don't remember :) We can discuss elsewhere, perhaps. – Will Robertson Jun 17 '14 at 8:32
  • BTW, is there an etex compatible macro to use instead of \chardef (like maybe \boxdef)? – John Kormylo Jun 18 '14 at 19:59
  • @JohnKormylo Not sure exactly what you mean — if you need larger values than \chardef allows you can use \mathchardef. \boxdef sounds like it would just be \newbox wouldn't it? – Will Robertson Jun 19 '14 at 4:27
1

If you use a temporary box register (like \box0) you must make sure that no macros are called which use the same box, and you must hope that no updated version or package replacement will ever use it either. However if you use \newsavebox, then it is safe from anyone else using \newsavebox (until you release it with \freebox).

\documentclass{article}

\makeatletter
\newcounter{free@boxes}% push stack counter
\newcounter{free@count}% loop counter

\global\let\old@savebox=\newsavebox% save original version

\global\chardef\free@min 255
\global\chardef\free@max 0

\newcommand*{\freebox}[1]% #1 = old savebox name
{\newif\ifgood\goodtrue%
\ifnum#1<\free@min \goodfalse\fi%
\ifnum#1>\free@max \goodfalse\fi%
\ifnum\value{free@boxes}=0\relax%
  \else\setcounter{free@count}{\value{free@boxes}}%
  \loop% check for duplicates
    \ifnum#1=\csname free@box\arabic{free@count}\endcsname
      \goodfalse%
      \setcounter{free@count}{0}%
    \else\addtocounter{free@count}{-1}\fi%
    \ifnum\value{free@count}>0 \repeat%
  \fi %
\ifgood\stepcounter{free@boxes}%
\global\expandafter\let\csname free@box\arabic{free@boxes}\endcsname#1%
\fi%
\global\chardef#1 0}

\renewcommand*{\newsavebox}[1]{% #1 = new savebox name
\ifnum\value{free@boxes}>0%
  \global\edef#1{\csname free@box\arabic{free@boxes}\endcsname}%
  \addtocounter{free@boxes}{-1}%
\else\old@savebox{#1}%
  \ifnum#1<\free@min \global\let\free@min=#1 \fi%
  \ifnum#1>\free@max \global\let\free@max=#1 \fi%
\fi}
\makeatother

\begin{document}
\newsavebox{\test}
\savebox{\test}{This is a test}
\usebox{\test}

\newsavebox{\testb}
\savebox{\testb}{This is the second test}
\usebox{\testb}

\freebox{\test}% release box registers for reuse
\freebox{\testb}

\newsavebox{\reuseb}% push stack returns second box first
\usebox{\reuseb}

\newsavebox{\reuse}
\usebox{\reuse}

The following have been reset to zero:\newline
\verb$\test$ \the\test\newline
\verb$\testb$ \the\testb

\makeatletter
The following should all equal the first box register value:\newline
\verb$\reuse$ \the\reuse\newline
\verb$\free@box1$ \the\csname free@box1\endcsname

The following should all equal the second box register value:\newline
\verb$\reuseb$ \the\reuseb\newline
\verb$\free@box2$ \the\csname free@box2\endcsname
\makeatother

\end{document}
  • 1
    Is this intended as an answer or a comment on the question? but why the complication, why not simply use the same box both times? – David Carlisle Jun 16 '14 at 17:52
  • I can find no sense in this, sorry. – egreg Jun 16 '14 at 18:04
  • @David Carlisle - The idea is that different macros by different authors could reuse the same box registers. Instead of trying to keep track of which boxes are still being used and which are not, this does it for you. Of course, it would work better to replace \newsavebox than introduce a new command \resusesavebox. – John Kormylo Jun 17 '14 at 1:22
  • @JohnKormylo I can't see a use case for this, either the box is only used in a controlled local scope in which case there is no need to allocate one you can use a scratch box such as 0 or 2 or 4 or \@tempboxa, or it needs to save box data across macros potentially from another package in which case you have nowhere to deallocate as you need to know the box has not been used when you come to use the saved value. – David Carlisle Jun 17 '14 at 9:12
  • @David Carlisle - The goal was not to use the contents of a previously filled savebox. This was just a test program to verify that it was working. – John Kormylo Jun 17 '14 at 12:11

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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