P
Phred Phungus
I'm looking at pp. 381-392 of _C Unleashed_ and set the goal of this
thread to read through the source of this text. I'll make a full source
listing after the sig.
$ ls -l
total 480
....
-rw-r--r-- 1 dan dan 8734 2000-06-08 16:13 dllist.c
-rw-r--r-- 1 dan dan 3935 2000-06-08 16:13 dllisteg.c
-rw-r--r-- 1 dan dan 3279 2000-06-08 16:13 dllist.h
-rw-r--r-- 1 dan dan 6614 2000-06-08 16:13 dllistmn.c
....
-rw-r--r-- 1 dan dan 4835 2010-02-04 22:48 sllist.c
-rw-r--r-- 1 dan dan 4777 2000-06-08 16:13 sllist.c~
-rw-r--r-- 1 dan dan 2851 2000-06-08 16:13 sllist.h
-rw-r--r-- 1 dan dan 3307 2000-06-08 16:13 sllistmn.c
I hardly know how to broach my subject without reading a program as I
see it. When I see things, I see what I'm looking for and can miss
obvious facts that lay slightly abreast. Since the source listing is
long, I thought it would be better to ask a concrete question about the
first thing that throws me.
Well, the first thing I see is
assert(Tag == 0);
This occurs in the function PrintBook. So caller must have the first
arg as zero, else execution aborts.
Why is Tag 0 when main calls?
--
fred
$ cat sl3.c
#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
#include "sllist.h"
typedef struct BOOK
{
char Title[30];
char Author[30];
} BOOK;
typedef struct FIELD_INFO
{
int TitleWidth;
int AuthWidth;
} FIELD_INFO;
int PrintBook(int Tag, void *Memory, void *Args)
{
BOOK *b = Memory;
FIELD_INFO *f = Args;
assert(Tag == 0);
printf("Read %*s, by %*s\n",
f->TitleWidth,
b->Title,
f->AuthWidth,
b->Author);
return 0;
}
int main(void)
{
BOOK Book[] =
{
{"Expert C Programming", "van der Linden"},
{"C Programming FAQs", "Summit"},
{"C++ Programming Language", "Stroustrup"},
{"Algorithms in C", "Sedgewick"},
{"Teach Yourself BCB", "Reisdorph"},
{"The Standard C Library", "Plauger"},
{"C++ Unleashed", "Liberty"},
{"Data Structures & Algorithms", "Lafore"},
{"C Programming Language", "Kernighan & Ritchie"},
{"Linux Unleashed", "Husain and Parker"},
{"C Unleashed", "Heathfield & Kirby"},
{"C : A Reference Manual", "Harbison & Steele"},
{"DOS Programmers Reference", "Dettmann & Johnson"},
{"C: How to Program", "Deitel & Deitel"},
{"Builder Unleashed", "Calvert"},
{"UNIX Unleashed", "Burk and Horvath"}
};
SLLIST *List = NULL;
SLLIST *Removed = NULL;
BOOK *Data;
FIELD_INFO FldInfo = { 30, 30};
size_t NumBooks = sizeof Book / sizeof Book[0];
size_t i;
/* Populate the list */
for(i = 0; i < NumBooks; i++)
{
if(SL_SUCCESS !=
SLFront(&List, 0, Book + i, sizeof(BOOK)))
{
puts("Couldn't allocate enough memory.");
SLDestroy(&List);
exit(EXIT_FAILURE);
}
}
/* Print the list */
SLWalk(List, PrintBook, &FldInfo);
/* Remove one item */
Removed = List;
for(i = 0; i < NumBooks / 2; i++)
{
Removed = Removed->Next;
}
Data = SLGetData(Removed->Next, NULL, NULL);
printf("\nRemoving title %s\n\n", Data->Title);
SLDeleteNext(Removed);
/* Print the list again to confirm deletion */
SLWalk(List, PrintBook, &FldInfo);
/* Destroy the list */
SLDestroy(&List);
return 0;
}
// gcc ll1.o -D_GNU_SOURCE -Wall -Wextra sl3.c -o out
$ cat sllist.h
/* sllist.h - header for single linked list lib
*
* SLLIST - Single-Linked List Library
*
* Copyright (C) 2000 Richard Heathfield
* Eton Computer Systems Ltd
* Macmillan Computer Publishing
*
* This program is free software; you can redistribute it
* and/or modify it under the terms of the GNU General
* Public License as published by the Free Software
* Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will
* be useful, but WITHOUT ANY WARRANTY; without even the
* implied warranty of MERCHANTABILITY or FITNESS FOR A
* PARTICULAR PURPOSE. See the GNU General Public License
* for more details.
*
* You should have received a copy of the GNU General
* Public License along with this program; if not, write
* to the Free Software Foundation, Inc., 675 Mass Ave,
* Cambridge, MA 02139, USA.
*
* Richard Heathfield may be contacted by email at:
* (e-mail address removed)
*
*/
#ifndef SLLIST_H__
#define SLLIST_H__
#define SL_SUCCESS 0
#define SL_NO_MEM 1
#define SL_ZERO_SIZE 2
typedef struct SLLIST
{
int Tag;
struct SLLIST *Next;
void *Object;
size_t Size;
} SLLIST;
/* Add new item immediately after current item */
int SLAdd(SLLIST **Item,
int Tag,
void *Object,
size_t Size);
/* Add item to front of list. Care: if you pass
* this function any node other than the first,
* you will get Y-branches in your list:
*
* oldroot-->-
* \
* >->-passeditem-->-->--oldnext
* /
* newitem-->-
*
* This would be a Bad Thing.
*/
int SLFront(SLLIST **Item,
int Tag,
void *Object,
size_t Size);
/* Add new item right at the end of the list */
int SLAppend(SLLIST **Item,
int Tag,
void *Object,
size_t Size);
/* Replace existing data */
int SLUpdate(SLLIST *Item,
int NewTag,
void *NewObject,
size_t NewSize);
/* Retrieve data from this node */
void *SLGetData(SLLIST *Item,
int *Tag,
size_t *Size);
/* Delete this item. Returns pointer to
* next item - caller's responsibility
* to maintain list integrity.
*/
SLLIST *SLDeleteThis(SLLIST *Item);
/* Delete item immediately following
* the one passed in. List integrity
* maintained automatically.
*/
void SLDeleteNext(SLLIST *Item);
/* Destroy the entire list */
void SLDestroy(SLLIST **List);
/* Call func(Tag, ThisItem, Args) for each item */
int SLWalk(SLLIST *List,
int(*Func)(int, void *, void *),
void *Args);
#endif
$ cat sllist.c
/* sllist.c - source for single linked list lib
*
* SLLIST - Single-Linked List Library
*
* Copyright (C) 2000 Richard Heathfield
* Eton Computer Systems Ltd
* Macmillan Computer Publishing
*
* This program is free software; you can redistribute it
* and/or modify it under the terms of the GNU General
* Public License as published by the Free Software
* Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will
* be useful, but WITHOUT ANY WARRANTY; without even the
* implied warranty of MERCHANTABILITY or FITNESS FOR A
* PARTICULAR PURPOSE. See the GNU General Public License
* for more details.
*
* You should have received a copy of the GNU General
* Public License along with this program; if not, write
* to the Free Software Foundation, Inc., 675 Mass Ave,
* Cambridge, MA 02139, USA.
*
* Richard Heathfield may be contacted by email at:
* (e-mail address removed)
*
*/
#include <stdlib.h>
#include <string.h>
#include <assert.h>
#include "sllist.h"
int SLAdd(SLLIST **Item,
int Tag,
void *Object,
size_t Size)
{
SLLIST *NewItem;
int Result = SL_SUCCESS;
assert(Item != NULL);
if(Size > 0)
{
NewItem = malloc(sizeof *NewItem);
if(NewItem != NULL)
{
NewItem->Tag = Tag;
NewItem->Size = Size;
NewItem->Object = malloc(Size);
if(NewItem->Object != NULL)
{
memcpy(NewItem->Object, Object, Size);
/* Handle empty list */
if(NULL == *Item)
{
NewItem->Next = NULL;
*Item = NewItem;
}
else /* Insert just after current item */
{
NewItem->Next = (*Item)->Next;
(*Item)->Next = NewItem;
}
}
else
{
free(NewItem);
Result = SL_NO_MEM;
}
}
else
{
Result = SL_NO_MEM;
}
}
else
{
Result = SL_ZERO_SIZE;
}
return Result;
}
int SLFront(SLLIST **Item,
int Tag,
void *Object,
size_t Size)
{
int Result = SL_SUCCESS;
SLLIST *p = NULL;
assert(Item != NULL);
Result = SLAdd(&p, Tag, Object, Size);
if(SL_SUCCESS == Result)
{
p->Next = *Item;
*Item = p;
}
return Result;
}
int SLAppend(SLLIST **Item,
int Tag,
void *Object,
size_t Size)
{
int Result = SL_SUCCESS;
SLLIST *EndSeeker;
assert(Item != NULL);
if(NULL == *Item)
{
Result = SLAdd(Item, Tag, Object, Size);
}
else
{
EndSeeker = *Item;
while(EndSeeker->Next != NULL)
{
EndSeeker = EndSeeker->Next;
}
Result = SLAdd(&EndSeeker, Tag, Object, Size);
}
return Result;
}
int SLUpdate(SLLIST *Item,
int NewTag,
void *NewObject,
size_t NewSize)
{
int Result = SL_SUCCESS;
void *p;
if(NewSize > 0)
{
p = realloc(Item->Object, NewSize);
if(NULL != p)
{
Item->Object = p;
memmove(Item->Object, NewObject, NewSize);
Item->Tag = NewTag;
Item->Size = NewSize;
}
else
{
Result = SL_NO_MEM;
}
}
else
{
Result = SL_ZERO_SIZE;
}
return Result;
}
void *SLGetData(SLLIST *Item,
int *Tag,
size_t *Size)
{
void *p = NULL;
if(Item != NULL)
{
if(Tag != NULL)
{
*Tag = Item->Tag;
}
if(Size != NULL)
{
*Size = Item->Size;
}
p = Item->Object;
}
return p;
}
SLLIST *SLDeleteThis(SLLIST *Item)
{
SLLIST *NextNode = NULL;
if(Item != NULL)
{
NextNode = Item->Next;
if(Item->Object != NULL)
{
free(Item->Object);
}
free(Item);
}
return NextNode;
}
void SLDeleteNext(SLLIST *Item)
{
if(Item != NULL && Item->Next != NULL)
{
Item->Next = SLDeleteThis(Item->Next);
}
}
void SLDestroy(SLLIST **List)
{
SLLIST *Next;
if(*List != NULL)
{
Next = *List;
do
{
Next = SLDeleteThis(Next);
} while(Next != NULL);
*List = NULL;
}
}
int SLWalk(SLLIST *List,
int(*Func)(int, void *, void *),
void *Args)
{
SLLIST *ThisItem;
int Result = 0;
for(ThisItem = List;
0 == Result && ThisItem != NULL;
ThisItem = ThisItem->Next)
{
Result = (*Func)(ThisItem->Tag,
ThisItem->Object,
Args);
}
return Result;
}
/* end of sllist.c */
// gcc -c -D_GNU_SOURCE -Wall -Wextra sllist.c -o ll1.o
$
thread to read through the source of this text. I'll make a full source
listing after the sig.
$ ls -l
total 480
....
-rw-r--r-- 1 dan dan 8734 2000-06-08 16:13 dllist.c
-rw-r--r-- 1 dan dan 3935 2000-06-08 16:13 dllisteg.c
-rw-r--r-- 1 dan dan 3279 2000-06-08 16:13 dllist.h
-rw-r--r-- 1 dan dan 6614 2000-06-08 16:13 dllistmn.c
....
-rw-r--r-- 1 dan dan 4835 2010-02-04 22:48 sllist.c
-rw-r--r-- 1 dan dan 4777 2000-06-08 16:13 sllist.c~
-rw-r--r-- 1 dan dan 2851 2000-06-08 16:13 sllist.h
-rw-r--r-- 1 dan dan 3307 2000-06-08 16:13 sllistmn.c
I hardly know how to broach my subject without reading a program as I
see it. When I see things, I see what I'm looking for and can miss
obvious facts that lay slightly abreast. Since the source listing is
long, I thought it would be better to ask a concrete question about the
first thing that throws me.
Well, the first thing I see is
assert(Tag == 0);
This occurs in the function PrintBook. So caller must have the first
arg as zero, else execution aborts.
Why is Tag 0 when main calls?
--
fred
$ cat sl3.c
#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
#include "sllist.h"
typedef struct BOOK
{
char Title[30];
char Author[30];
} BOOK;
typedef struct FIELD_INFO
{
int TitleWidth;
int AuthWidth;
} FIELD_INFO;
int PrintBook(int Tag, void *Memory, void *Args)
{
BOOK *b = Memory;
FIELD_INFO *f = Args;
assert(Tag == 0);
printf("Read %*s, by %*s\n",
f->TitleWidth,
b->Title,
f->AuthWidth,
b->Author);
return 0;
}
int main(void)
{
BOOK Book[] =
{
{"Expert C Programming", "van der Linden"},
{"C Programming FAQs", "Summit"},
{"C++ Programming Language", "Stroustrup"},
{"Algorithms in C", "Sedgewick"},
{"Teach Yourself BCB", "Reisdorph"},
{"The Standard C Library", "Plauger"},
{"C++ Unleashed", "Liberty"},
{"Data Structures & Algorithms", "Lafore"},
{"C Programming Language", "Kernighan & Ritchie"},
{"Linux Unleashed", "Husain and Parker"},
{"C Unleashed", "Heathfield & Kirby"},
{"C : A Reference Manual", "Harbison & Steele"},
{"DOS Programmers Reference", "Dettmann & Johnson"},
{"C: How to Program", "Deitel & Deitel"},
{"Builder Unleashed", "Calvert"},
{"UNIX Unleashed", "Burk and Horvath"}
};
SLLIST *List = NULL;
SLLIST *Removed = NULL;
BOOK *Data;
FIELD_INFO FldInfo = { 30, 30};
size_t NumBooks = sizeof Book / sizeof Book[0];
size_t i;
/* Populate the list */
for(i = 0; i < NumBooks; i++)
{
if(SL_SUCCESS !=
SLFront(&List, 0, Book + i, sizeof(BOOK)))
{
puts("Couldn't allocate enough memory.");
SLDestroy(&List);
exit(EXIT_FAILURE);
}
}
/* Print the list */
SLWalk(List, PrintBook, &FldInfo);
/* Remove one item */
Removed = List;
for(i = 0; i < NumBooks / 2; i++)
{
Removed = Removed->Next;
}
Data = SLGetData(Removed->Next, NULL, NULL);
printf("\nRemoving title %s\n\n", Data->Title);
SLDeleteNext(Removed);
/* Print the list again to confirm deletion */
SLWalk(List, PrintBook, &FldInfo);
/* Destroy the list */
SLDestroy(&List);
return 0;
}
// gcc ll1.o -D_GNU_SOURCE -Wall -Wextra sl3.c -o out
$ cat sllist.h
/* sllist.h - header for single linked list lib
*
* SLLIST - Single-Linked List Library
*
* Copyright (C) 2000 Richard Heathfield
* Eton Computer Systems Ltd
* Macmillan Computer Publishing
*
* This program is free software; you can redistribute it
* and/or modify it under the terms of the GNU General
* Public License as published by the Free Software
* Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will
* be useful, but WITHOUT ANY WARRANTY; without even the
* implied warranty of MERCHANTABILITY or FITNESS FOR A
* PARTICULAR PURPOSE. See the GNU General Public License
* for more details.
*
* You should have received a copy of the GNU General
* Public License along with this program; if not, write
* to the Free Software Foundation, Inc., 675 Mass Ave,
* Cambridge, MA 02139, USA.
*
* Richard Heathfield may be contacted by email at:
* (e-mail address removed)
*
*/
#ifndef SLLIST_H__
#define SLLIST_H__
#define SL_SUCCESS 0
#define SL_NO_MEM 1
#define SL_ZERO_SIZE 2
typedef struct SLLIST
{
int Tag;
struct SLLIST *Next;
void *Object;
size_t Size;
} SLLIST;
/* Add new item immediately after current item */
int SLAdd(SLLIST **Item,
int Tag,
void *Object,
size_t Size);
/* Add item to front of list. Care: if you pass
* this function any node other than the first,
* you will get Y-branches in your list:
*
* oldroot-->-
* \
* >->-passeditem-->-->--oldnext
* /
* newitem-->-
*
* This would be a Bad Thing.
*/
int SLFront(SLLIST **Item,
int Tag,
void *Object,
size_t Size);
/* Add new item right at the end of the list */
int SLAppend(SLLIST **Item,
int Tag,
void *Object,
size_t Size);
/* Replace existing data */
int SLUpdate(SLLIST *Item,
int NewTag,
void *NewObject,
size_t NewSize);
/* Retrieve data from this node */
void *SLGetData(SLLIST *Item,
int *Tag,
size_t *Size);
/* Delete this item. Returns pointer to
* next item - caller's responsibility
* to maintain list integrity.
*/
SLLIST *SLDeleteThis(SLLIST *Item);
/* Delete item immediately following
* the one passed in. List integrity
* maintained automatically.
*/
void SLDeleteNext(SLLIST *Item);
/* Destroy the entire list */
void SLDestroy(SLLIST **List);
/* Call func(Tag, ThisItem, Args) for each item */
int SLWalk(SLLIST *List,
int(*Func)(int, void *, void *),
void *Args);
#endif
$ cat sllist.c
/* sllist.c - source for single linked list lib
*
* SLLIST - Single-Linked List Library
*
* Copyright (C) 2000 Richard Heathfield
* Eton Computer Systems Ltd
* Macmillan Computer Publishing
*
* This program is free software; you can redistribute it
* and/or modify it under the terms of the GNU General
* Public License as published by the Free Software
* Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will
* be useful, but WITHOUT ANY WARRANTY; without even the
* implied warranty of MERCHANTABILITY or FITNESS FOR A
* PARTICULAR PURPOSE. See the GNU General Public License
* for more details.
*
* You should have received a copy of the GNU General
* Public License along with this program; if not, write
* to the Free Software Foundation, Inc., 675 Mass Ave,
* Cambridge, MA 02139, USA.
*
* Richard Heathfield may be contacted by email at:
* (e-mail address removed)
*
*/
#include <stdlib.h>
#include <string.h>
#include <assert.h>
#include "sllist.h"
int SLAdd(SLLIST **Item,
int Tag,
void *Object,
size_t Size)
{
SLLIST *NewItem;
int Result = SL_SUCCESS;
assert(Item != NULL);
if(Size > 0)
{
NewItem = malloc(sizeof *NewItem);
if(NewItem != NULL)
{
NewItem->Tag = Tag;
NewItem->Size = Size;
NewItem->Object = malloc(Size);
if(NewItem->Object != NULL)
{
memcpy(NewItem->Object, Object, Size);
/* Handle empty list */
if(NULL == *Item)
{
NewItem->Next = NULL;
*Item = NewItem;
}
else /* Insert just after current item */
{
NewItem->Next = (*Item)->Next;
(*Item)->Next = NewItem;
}
}
else
{
free(NewItem);
Result = SL_NO_MEM;
}
}
else
{
Result = SL_NO_MEM;
}
}
else
{
Result = SL_ZERO_SIZE;
}
return Result;
}
int SLFront(SLLIST **Item,
int Tag,
void *Object,
size_t Size)
{
int Result = SL_SUCCESS;
SLLIST *p = NULL;
assert(Item != NULL);
Result = SLAdd(&p, Tag, Object, Size);
if(SL_SUCCESS == Result)
{
p->Next = *Item;
*Item = p;
}
return Result;
}
int SLAppend(SLLIST **Item,
int Tag,
void *Object,
size_t Size)
{
int Result = SL_SUCCESS;
SLLIST *EndSeeker;
assert(Item != NULL);
if(NULL == *Item)
{
Result = SLAdd(Item, Tag, Object, Size);
}
else
{
EndSeeker = *Item;
while(EndSeeker->Next != NULL)
{
EndSeeker = EndSeeker->Next;
}
Result = SLAdd(&EndSeeker, Tag, Object, Size);
}
return Result;
}
int SLUpdate(SLLIST *Item,
int NewTag,
void *NewObject,
size_t NewSize)
{
int Result = SL_SUCCESS;
void *p;
if(NewSize > 0)
{
p = realloc(Item->Object, NewSize);
if(NULL != p)
{
Item->Object = p;
memmove(Item->Object, NewObject, NewSize);
Item->Tag = NewTag;
Item->Size = NewSize;
}
else
{
Result = SL_NO_MEM;
}
}
else
{
Result = SL_ZERO_SIZE;
}
return Result;
}
void *SLGetData(SLLIST *Item,
int *Tag,
size_t *Size)
{
void *p = NULL;
if(Item != NULL)
{
if(Tag != NULL)
{
*Tag = Item->Tag;
}
if(Size != NULL)
{
*Size = Item->Size;
}
p = Item->Object;
}
return p;
}
SLLIST *SLDeleteThis(SLLIST *Item)
{
SLLIST *NextNode = NULL;
if(Item != NULL)
{
NextNode = Item->Next;
if(Item->Object != NULL)
{
free(Item->Object);
}
free(Item);
}
return NextNode;
}
void SLDeleteNext(SLLIST *Item)
{
if(Item != NULL && Item->Next != NULL)
{
Item->Next = SLDeleteThis(Item->Next);
}
}
void SLDestroy(SLLIST **List)
{
SLLIST *Next;
if(*List != NULL)
{
Next = *List;
do
{
Next = SLDeleteThis(Next);
} while(Next != NULL);
*List = NULL;
}
}
int SLWalk(SLLIST *List,
int(*Func)(int, void *, void *),
void *Args)
{
SLLIST *ThisItem;
int Result = 0;
for(ThisItem = List;
0 == Result && ThisItem != NULL;
ThisItem = ThisItem->Next)
{
Result = (*Func)(ThisItem->Tag,
ThisItem->Object,
Args);
}
return Result;
}
/* end of sllist.c */
// gcc -c -D_GNU_SOURCE -Wall -Wextra sllist.c -o ll1.o
$