[Tex/LaTex] Simple (execution) stack with pointers and comments using TikZ

stacktikz-pgf

I'm looking for a simple way to draw a stack. I know about drawstack.sty. I actually love the stacks produced by this package but the size is way too big as I'm using IEEEtran for my paper. The stack should use as less space as possible (i.e. fit the text size). This answer produces the desired result but I'm looking for a way to additionally draw pointers and comments (see the mockup below). I'm absolutely new to TikZ and therefore have no idea how to achieve this.

enter image description here

Best Answer

Using tikz \matrix and some styles defined later in this answer you can code your stack like this:

\begin{tikzpicture}
  \matrix [memory] {
        &           n/sh     \\
        & |(bi)|    //bi     \\
        & |(cmd)|   cmd      \\
   blub & |(sys)|   \&system \\
};
\node[pointer, right=2ex of sys] (esp) {esp};

\draw[->] (esp) -- (sys);
\draw[->] (cmd.east) to[out=-10,in=10] (bi.east);
\end{tikzpicture}

Note how simple is the syntax. The stack is basically a matrix with two columns. The first one is for labels or addresses, the second one are the contents. Each cell can have a name with the syntax |(name)|. Those names can be used later to draw arrows, pointers, etc. The result is:

Simple Stack

You can also give it other attributes. For example, putting |[!!]| in a cell marks it as important, and it gets highlighted. You can mark a cell as |[break above]| to get a wavy border that suggest that the memory continues. As in the following examples:

\begin{tikzpicture}
  \matrix [memory] {
        & |[break above]| \ldots   \\
        &                 n/sh     \\
        & |(bi)|          //bi     \\
        & |(cmd)|         cmd      \\
   blub & |[!!] (sys)|    \&system \\
};
\node[pointer, right=2ex of sys] (esp) {esp};
\draw[->] (esp) -- (sys);
\draw[->] (cmd.east) to[out=-10,in=10] (bi.east);
\end{tikzpicture}

Which produces:

Another example

Now, the promised code which defines those styles:

\usetikzlibrary{shapes.symbols,matrix, positioning}
\tikzset{
   memory/.style={
        matrix of nodes, name=M,
        every node/.append style={
               font=\tt, outer xsep=.4ex,
               anchor=base},
        column 2/.append style={
               every node/.append style=
                    {draw,fill=white, 
                     minimum width=#1, 
                     minimum height=1.5em}
                }, 
          row sep=-.4pt,
       },
   memory/.default=1.6cm,
   break above/.style={shape=tape, tape bend top=in and out, tape bend bottom=none},
   break below/.style={shape=tape, tape bend top=none, tape bend bottom=in and out},
   !!/.style={fill=green!20},
   pointer/.style = {font=\tt, anchor=base, inner sep=2pt},
}

Note that the style memory accepts one parameter which is the minimum width of each cell. You can then write \matrix[memory=1cm] for example. The default is 1.6cm. Note however that wider cells will use the required width and thus "break" the figure homogeneity. If you have wide cells, you'll have to adjust the value of the memory parameter to the width ot that wide cells.