

\documentstyle{article}

\setlength{\oddsidemargin}{0in}
\setlength{\evensidemargin}{0in}
\setlength{\topmargin}{0.0in}
\setlength{\headheight}{0in}
\setlength{\headsep}{0in}
\setlength{\textwidth}{6.5in}
\setlength{\textheight}{9.4in}
\setlength{\parindent}{0in}
\setlength{\parskip}{0.12in}

\begin{document}

\newcommand{\bfs}[1]{{\bf #1}}

\begin{center}
{\LARGE\bf 

A Closer Look at the Warehouse Program

}
\end{center}

\bigskip

In this handout, we use \bfs{gdb} to do more exploration of how pointers
work in the warehouse program.  (Note:  We are not using \bfs{gdb} for
debugging here; we are just using it as a convenient way to print out
some information on the program's actions.)

\begin{verbatim}
  1  Script started on Mon Apr 27 22:15:30 1992
  2  heather% gdb a.out
  3  GDB is free software and you are welcome to distribute copies of it
  4   under certain conditions; type "info copying" to see the conditions.
  5  There is absolutely no warranty for GDB; type "info warranty" for details.
  6  GDB 4.1, Copyright 1991 Free Software Foundation, Inc...
  7  (gdb) l 130
  8  125     
  9  126     GetData()  /* prompt user for the information, and put it in
 10  127                   the struct pointed to by CurrPtr */
 11  128     
 12  129     {  int ItmNm,TmStmp,CstmrID;  
 13  130     
 14  131        printf("enter item number, time stamp and customer i.d.\n");
 15  132        scanf("%d%d%d",&ItmNm,&TmStmp,&CstmrID);
 16  133     
 17  134        /* create new node */
 18  (gdb) 
 19  135        CurrPtr = (NodePtrType) calloc(1,sizeof(struct ListNode));  
 20  136     
 21  137        /* now fill it with the data */
 22  138        CurrPtr->ItemNum = ItmNm;
 23  139        CurrPtr->TimeStamp = TmStmp;
 24  140        CurrPtr->CustomerID = CstmrID;
 25  141     
 26  142        /* this node is not connected to anything yet */
 27  143        CurrPtr->Link = 0;  
 28  144     }
 29  (gdb) 
 30  145     
 31  146     
 32  147     Insert()  /* inserts the struct pointed to by CurrPtr into the
 33  148                  list */
 34  149     
 35  150     {  NodePtrType LeadingPtr,TrailingPtr;
 36  151     
 37  152        /* list currently empty? */
 38  153        if (ListHead == 0)  {
 39  154           ListHead = CurrPtr;
 40  (gdb) 
 41  155           return;
 42  156        }
 43  157        
 44  158        /* current time stamp earlier than list head? */
 45  159        if (CurrPtr->TimeStamp < ListHead->TimeStamp)  {
 46  160           CurrPtr->Link = ListHead;
 47  161           ListHead = CurrPtr;
 48  162           return;
 49  163        }
 50  164        
 51  (gdb) 
 52  165        LeadingPtr = ListHead->Link;  TrailingPtr = ListHead;
 53  166        while (1)  {
 54  167     
 55  168           /* reached end of list? */
 56  169           if (LeadingPtr == 0)  {
 57  170              TrailingPtr->Link = CurrPtr;
 58  171              break;
 59  172           }
 60  173     
 61  174           /* arrived at insertion point? */
 62  (gdb) 
 63  175           if (CurrPtr->TimeStamp < LeadingPtr->TimeStamp)  {
 64  176              TrailingPtr->Link = CurrPtr;
 65  177              CurrPtr->Link = LeadingPtr;
 66  178              return;
 67  179           }
 68  180           /* otherwise move to next node */
 69  181           else  {
 70  182              TrailingPtr = LeadingPtr;
 71  183              LeadingPtr = LeadingPtr->Link;
 72  184           }
 73  (gdb) 
 74  185        }
 75  186     }
 76  187     
 77  188     
 78  189     Cancel()  /* delete the node whose time stamp matches CancelTmStmp;
 79  190                  to keep the program simple so as to ease the teaching 
 80  191                  about pointers, it is assumed that there will be one, 
 81  192                  and only one, node which matches the given time stamp */
 82  193     
 83  194     {  NodePtrType LeadingPtr,TrailingPtr;
 84  (gdb) b 138
 85  Breakpoint 1 at 0x2544: file Warehouse.c, line 138.
 86  (gdb) ignore 1 2
 87  Will ignore next 2 crossings of breakpoint 1.
 88  (gdb) r
 89  Starting program: /1/home/matloff/Courses/40/Progs/a.out 
 90  read in a file?
 91  n
 92  enter command
 93  p
 94  enter item number, time stamp and customer i.d.
 95  234 44 1
 96  enter command
 97  p
 98  enter item number, time stamp and customer i.d.
 99  17 68 220
100  enter command
101  p
102  enter item number, time stamp and customer i.d.
103  4 56 18
104  
105  Breakpoint 1, GetData () at Warehouse.c:138
106  138        CurrPtr->ItemNum = ItmNm;
107  (gdb) p CurrPtr
108  $1 = (NodePtrType) 0x6710
109  (gdb) b 175
110  Breakpoint 2 at 0x2654: file Warehouse.c, line 175.
111  (gdb) c
112  Continuing.
113  
114  Breakpoint 2, Insert () at Warehouse.c:175
115  175           if (CurrPtr->TimeStamp < LeadingPtr->TimeStamp)  {
116  (gdb) define cld
117  Type commands for definition of "cld".
118  End with a line saying just "end".
119  call Display()
120  end
121  (gdb) disp LeadingPtr
122  1: LeadingPtr = (NodePtrType) 0x66f8
123  (gdb) disp TrailingPtr
124  2: TrailingPtr = (NodePtrType) 0x66e0
125  (gdb) cld
126  66e0 234 44 1 66f8
127  66f8 17 68 220 0
128  $2 = 17832
129  (gdb) n
130  176              TrailingPtr->Link = CurrPtr;
131  2: TrailingPtr = (NodePtrType) 0x66e0
132  1: LeadingPtr = (NodePtrType) 0x66f8
133  (gdb) n
134  177              CurrPtr->Link = LeadingPtr;
135  2: TrailingPtr = (NodePtrType) 0x66e0
136  1: LeadingPtr = (NodePtrType) 0x66f8
137  (gdb) cld
138  66e0 234 44 1 6710
139  6710 4 56 18 0
140  $3 = 17832
141  (gdb) p *LeadingPtr
142  $4 = {ItemNum = 17, TimeStamp = 68, CustomerID = 220, Link = 0x0}
143  (gdb) n
144  178              return;
145  2: TrailingPtr = (NodePtrType) 0x66e0
146  1: LeadingPtr = (NodePtrType) 0x66f8
147  (gdb) cld
148  66e0 234 44 1 6710
149  6710 4 56 18 66f8
150  66f8 17 68 220 0
151  $5 = 17832
152  (gdb) qy
153  heather% e
154  heather% 
155  script done on Mon Apr 27 22:21:20 1992
\end{verbatim}


\bigskip

\bfs{Note:  Except when stated otherwise, all line numbers below refer to 
those of the \bfs{script} file, not those of the C source file.}

\bfs{Overview:}  In this example, the user will input three purchase
orders, with data

\begin{verbatim}
234 44 1
17 68 220
4 56 18
\end{verbatim}

After the third purchase order is entered, we will watch as it is inserted
into the linked list.

\bfs{Lines 9-186:}  Here I have used the \bfs{list} command to list the 
part of the program on which we will focus.  

GetData() gets the data from the user (Lines 14-15), creates a new 
ListNode ``box,'' points CurrPtr to it (Line 19), and then stores
the user's data into that box (Lines 22-24).

Insert() inserts this new box into the linked list.  Its main portion
is a \bfs{while} loop (Lines 53-74), which is used to traverse the linked
list; each iteration of the loop makes us go to the next node in the
list (see comment, Line 68).

\bfs{Line 84:}  I have set a breakpoint (at Line 22), right after we create 
the new box and point CurrPtr to it (Line 19).  This way I can print out 
the value of CurrPtr at that time, to know the address of the new box, for 
reference when we go through Insert() later on.  I have asked \bfs{gdb} to 
skip the first two times we hit this breakpoint (Line 86), since I am only 
interested in what happens at the third purchase order. 

\bfs{Line 88:}  OK, we're running now.

\bfs{Lines 103ff:}  The user enters the third purchase order (Line 103),
and sure enough, \bfs{gdb} does stop at the breakpoint (Line 105).  I
ask to see what the address of the newly-created box is, and it turns
out to be 0x6710 (Lines 107-108).

Now I take advantage of the pause, and set my other breakpoint (Line 109), 
which is in the function Insert().  This breakpoint (Line 63) is the
first non-special-case statement in the \bfs{while} loop mentioned above.
We insert this breakpoint so that we can watch closely as the new box
is inserted into the list.  

\bfs{Line 111:}  So, let's get on with it.

\bfs{Lines 114ff:}  Now we have hit that breakpoint in Insert().  From
this point onward, we will be single-stepping through the code (Lines
129, 133, 143), to get a detailed look.  At each line, I want to call
Display() (recall this function prints out the whole linked list), but
I want to avoid the tedium of repeatedly typing

\begin{verbatim}
call Display()
\end{verbatim}

so I make use of \bfs{gdb}'s \bfs{define} command (Lines 116-120).  From
now on, I can indulge my laziness by typing `cld' (Lines 125, 137, 147),
which is much shorter to type.\footnote{It is not just laziness.  The less 
I have to bother myself with typing, the better I can concentrate on 
finding my bug, though again, in this particular case I am not using
\bfs{gdb} for debugging purposes.}

I am also arranging for the current values of LeadingPtr and TrailingPtr
to print out at every step (Lines 121, 123), which I want since they are
key variables in this loop.  Basically, here is what they are used for
(Lines 52-74):  Recall that the \bfs{while} loop takes us on a tour of
the linked list, one node per loop iteration.  During each iteration,
LeadingPtr will point to some node in the list, and TrailingPointer 
to the node right behind that node (Lines 52, 70-71).  

Eventually we will reach the insertion point, in between two boxes,
which I will call oldbox-left and oldbox-right.  Let's call our new
box newbox.  Right now, oldbox-left is connected forward to oldbox-right.
We want to change that so that oldbox-left is connected forward to
newbox, and newbox is connected forward to oldbox-right.  We can make
these connections by keeping in mind the pointers which are pointing
to them:

\begin{verbatim}
TrailingPtr    oldbox-left     
LeadingPtr     oldbox-right    
CurrPtr        newbox          
\end{verbatim}

In Line 64, oldbox-left will be connected forward to newbox, and in Line
65, newbox will be connected forward to oldbox-right.

\bfs{Lines 125-128:}  Here we see what the linked list looks like right
now (before inserting the new box).  As expected, we see that the list
consists of two boxes, corresponding to the first two purchase orders. 
The two boxes are at addresses 66e0 and 66f8.  

Note that when we say that the second box is ``connected'' to the first,
we do \underline{not} mean this in any physical sense; we only mean that
we have set the Link field of the first box, 66f8, to the address of the
second box.  This is absolutely meaningless to the hardware---we can put
any value into any memory location, including putting the address of one
location into another location, and the hardware won't care what we put
where---but \underline{\bf WE} make it meaningful by writing our program to
follow this trail.  For example, we wrote the Display() function to include a
line

\begin{verbatim}
TmpPtr = TmpPtr->Link;
\end{verbatim}

(Line 65 of the original struct/pointers handout), which changes TmpPtr
from pointing to one box to pointing to the next box in the linked
list.\footnote{Kevin Rich made a nice analogy to all of this:  Suppose
you are playing some kind of game, like a scavenger hunt in a home, in
which each clue leads you to the next.  Say the clues are in notes 
inside of envelopes.  Your first envelope note might, in addition to
giving you your first clue, say, ``Go to the kitchen to get your next
clue.''  You go to the kitchen, and find an envelope there.  The note
in the envelope contains your next clue, and in addition says, ``Your
next clue is in the bathroom.''  You then go to the bathroom, where
you find another envelope, and so on.  The point is that these envelopes
can be scattered all over the house, anywhere, not next to each other.
And if, say, I want to add a new clue in the garage, that is acquired
after the one in the kitchen but before the one in the bathroom, I
simply change the note in the kitchen to say, ``Go to the garage,''
and write the note in the garage to say, ``Your next clue is in the
bathroom.''}

\bfs{Lines 129ff:}  Now we are single-stepping through the code which
will insert our newest purchase order,

\begin{verbatim}
4 56 18
\end{verbatim}

into the list, where the list currently contains the purchase orders

\begin{verbatim}
234 44 1
17 68 220
\end{verbatim}

So the new order (which we called newbox above), with time stamp 56, should
go between the existing ones with time stamps 44 (oldbox-left) and 68
(oldbox-right).

\bfs{Line 130:}  Remember, one of the things we must do is connect
the time-44 purchase order (pointed to by TrailingPtr) forward with our
new one (pointed to by CurrPtr).  That is what this line does.

\bfs{Line 134:}  The other thing we must do is connect our new box
(pointed to by CurrPtr) forward with our time-68 purchase order (pointed
to by LeadingPtr).  We do that in this line.

\bfs{Lines 137ff:}  OK, let's call Display() to take a look around.
There's the time-44 purchase order, still at the head of the list,
just as it should be.  And there's the time-56 order, the new one,
which we now see is successfully connected to the time-44 order
(the fifth field on Line 138 is 6710, and the first field in Line
139 is 6710).  

But how come the time-68 purchase order has disappeared?  Well, it
is still there, but it wasn't picked up by our call to Display(),
for the following reason:  We have written Display(), as mentioned 
earlier, to step through the linked list, using the Link field in
one box to get to the next box.  Well, since on Line 133 we executed
Line 130, the link that formerly had existed between the time-44
purchase order and the time-68 purchase order (as recently as Lines
126-127) has now been broken, with the time-44 purchase order now
connected instead to our new time-56 purchase order.

But to make sure that the time-68 purchase order is still there, I
gave the \bfs{gdb} command

\begin{verbatim}
p *LeadingPtr
\end{verbatim}

on Line 141.  This says, ``print the object pointed to by LeadingPtr.''
That object is the struct which contains our time-68 purchase order,
which is now printed out (Line 142).

\bfs{Line 143:}  Now we execute Line 134, which will complete the
insertion, by literally providing the ``missing link'' that we just
discussed above, i.e. we will connect the new box to the time-68 box.
To see that it all worked out correctly, we call Display() again
(Lines-147-150), and we see that the three purchase orders are indeed
connected correctly:  The time-44 order has 6710 in its Link field,
and the time-56 order is at 6710; the time-56 order has 66f8 in its
Link field, and the time-68 order is at 66f8.

\end{document}


