473,395 Members | 1,441 Online
Bytes | Software Development & Data Engineering Community
Post Job

Home Posts Topics Members FAQ

Join Bytes to post your question to a community of 473,395 software developers and data experts.

Could anyone explain the code for me?

The following code is for list operation. But I can not understand.
Could anyone explain the code for me?

/*
* List definitions.
*/

#define LIST_HEAD(name, type)
struct name {
type *lh_first; /* first element */
}
#define LIST_ENTRY(type)
struct {
type *le_next; /* next element */
type **le_prev; /* address of previous next element */
}

Questions:
Why the struct does not have a name?
Is the list a two-way list?

/*
* List functions.
*/
#define LIST_INIT(head) {
(head)->lh_first = NULL;
}

#define LIST_INSERT_AFTER(listelm, elm, field) {
if (((elm)->field.le_next = (listelm)->field.le_next) != NULL)
(listelm)->field.le_next->field.le_prev =
&(elm)->field.le_next;
(listelm)->field.le_next = (elm);
(elm)->field.le_prev = &(listelm)->field.le_next;
}

Question:
What is listelm, elm, field?

#define LIST_INSERT_HEAD(head, elm, field) {
if (((elm)->field.le_next = (head)->lh_first) != NULL)
(head)->lh_first->field.le_prev =
&(elm)->field.le_next;
(head)->lh_first = (elm);
(elm)->field.le_prev = &(head)->lh_first;
}

Question:

If elm becomes head, what's the purpose of the last sentence:
(elm)->field.le_prev = &(head)->lh_first;
Thanks in advance.

Jack
Jul 22 '05 #1
13 2421
C++fan wrote:
The following code is for list operation. But I can not understand.
Could anyone explain the code for me?

/*
* List definitions.
*/

#define LIST_HEAD(name, type) This doesn't do anything useful.
struct name {
type *lh_first; /* first element */
}
Missing semi-colon after struct definition.
#define LIST_ENTRY(type) See above.
struct {
type *le_next; /* next element */
type **le_prev; /* address of previous next element */ I suspect le_prev's comment is wrong. Surely le_prev is the previous
node in the list, not the previous le_next (which is /this/ node).
}

Questions:
Why the struct does not have a name?
Looks like an error to me.
Is the list a two-way list? Well there are pointers to both previous and next nodes...

/*
* List functions.
*/
#define LIST_INIT(head) {
(head)->lh_first = NULL;
}
That isn't how macros work. Read a textbook.

#define LIST_INSERT_AFTER(listelm, elm, field) {
if (((elm)->field.le_next = (listelm)->field.le_next) != NULL)
(listelm)->field.le_next->field.le_prev =
&(elm)->field.le_next;
(listelm)->field.le_next = (elm);
(elm)->field.le_prev = &(listelm)->field.le_next;
}

Question:
What is listelm, elm, field? They're arguments to a function-style macro. Whoever wrote this doesn't
understand macros, and should be using functions instead.


#define LIST_INSERT_HEAD(head, elm, field) {
if (((elm)->field.le_next = (head)->lh_first) != NULL)
(head)->lh_first->field.le_prev =
&(elm)->field.le_next;
(head)->lh_first = (elm);
(elm)->field.le_prev = &(head)->lh_first;
}

Question:

If elm becomes head, what's the purpose of the last sentence:
(elm)->field.le_prev = &(head)->lh_first;


How about using functions so we can see what the types of the arguments
are? If possible, post a compileable example.

HTH,
Jacques.

Jul 22 '05 #2
C++fan skrev i meldingen
<15**************************@posting.google.com>. ..
The following code is for list operation. But I can not understand.
Could anyone explain the code for me?


It's an attempt at C++ code written by someone probably learning
basic programming. It's not even syntactically correct. Searching
for "meaning" in such code is useless; evaluate on syntax only.

Jul 22 '05 #3
"C++fan" <jw****@excite.com> wrote in message
news:15**************************@posting.google.c om...
The following code is for list operation. But I can not understand.
Could anyone explain the code for me?

/*
* List definitions.
*/

#define LIST_HEAD(name, type)
struct name {
type *lh_first; /* first element */
}
#define LIST_ENTRY(type)
struct {
type *le_next; /* next element */
type **le_prev; /* address of previous next element */
}

Questions:
Why the struct does not have a name?
Is the list a two-way list?

/*
* List functions.
*/
#define LIST_INIT(head) {
(head)->lh_first = NULL;
}

#define LIST_INSERT_AFTER(listelm, elm, field) {
if (((elm)->field.le_next = (listelm)->field.le_next) != NULL)
(listelm)->field.le_next->field.le_prev =
&(elm)->field.le_next;
(listelm)->field.le_next = (elm);
(elm)->field.le_prev = &(listelm)->field.le_next;
}

Question:
What is listelm, elm, field?

#define LIST_INSERT_HEAD(head, elm, field) {
if (((elm)->field.le_next = (head)->lh_first) != NULL)
(head)->lh_first->field.le_prev =
&(elm)->field.le_next;
(head)->lh_first = (elm);
(elm)->field.le_prev = &(head)->lh_first;
}

Question:

If elm becomes head, what's the purpose of the last sentence:
(elm)->field.le_prev = &(head)->lh_first;
Thanks in advance.

Jack


Jack, that's quite a puzzle. As a true "C++fan" I hope you won't actually
use crap like this unless you have to! (Hint: std::list)

Anyway, I'm far from sure of this but maybe it is used as follows:

struct fred_node
{
LIST_ENTRY(struct fred_node) node;
Fred fred; // Fred is some arbitrary type -- this is a list of Freds
};

which translates to:

struct fred_node
{
struct {
struct fred_node *le_next; /* next element */
struct fred_node **le_prev; /* address of previous next element */
} node;
Fred fred; // Fred is some arbitrary type -- this is a list of Freds
};

This defines the node type. Then make the list head:

LIST_HEAD(fred_head, struct fred_node) fredlist;
LIST_INIT(fredlist);

which is equivalent to:

struct fred_head {
struct fred_node *lh_first; /* first element */
} fredlist;
fredlist->lh_first = NULL;

Now add a node:

struct fred_node *new_node = (struct fred_node *) malloc(sizeof(struct
fred_node));
new_node.fred = Fred(21); // whatever that means
LIST_INSERT_HEAD(mylist, new_node, node);

which expands to

struct fred_node *new_node = (struct fred_node *) malloc(sizeof(struct
fred_node));
new_node.fred = Fred(21); // whatever that means
if ((new_node->node.le_next = (fredlist)->lh_first) != NULL)
fredlist->lh_first->node.le_prev = &new_node->node.le_next;
fredlist->lh_first = new_node;
new_node->node.le_prev = &new_node;

Now add another node:

struct fred_node *newer_node = (struct fred_node *) malloc(sizeof(struct
fred_node));
newer_node.fred = Fred(-33); // whatever that means
LIST_INSERT_AFTER(newer_node, new_node, node);

which expands to:

struct fred_node *newer_node = (struct fred_node *) malloc(sizeof(struct
fred_node));
newer_node.fred = Fred(-33); // whatever that means
if ((new_node->node.le_next = newer_node->node.le_next) != NULL)
newer_node->node.le_next->node.le_prev = &new_node->node.le_next;
newer_node->node.le_next = new_node;
new_node->node.le_prev = &new_node;

Well, that's what I came up with. I didn't test anything. Good luck.

--
Cy
http://home.rochester.rr.com/cyhome/
Jul 22 '05 #4
C++fan wrote:
The following code is for list operation. But I can not understand.
Could anyone explain the code for me?

/*
* List definitions.
*/

#define LIST_HEAD(name, type)
struct name {
type *lh_first; /* first element */
}
#define LIST_ENTRY(type)
struct {
type *le_next; /* next element */
type **le_prev; /* address of previous next element */
}


<snip> more of the same </snip>

That's the sort of code people used to write when they wanted to do
generic programming. Awful, isn't it? This is why templates were
introduced to C++.

Jul 22 '05 #5
Hi Jacques:

Thanks a lot.
The code is modified from /sys/queue.h of FreeBSD. Below is the link:
http://fxr.watson.org/fxr/source/sys/queue.h

The original code is from line 328 to 380. But I can not completely
understand it. It is confusing.

Regards,

Jack

Jacques Labuschagne <ja*****@clawshrimp.com> wrote in message news:<Ls********************@news02.tsnz.net>...
C++fan wrote:
The following code is for list operation. But I can not understand.
Could anyone explain the code for me?

/*
* List definitions.
*/

#define LIST_HEAD(name, type) This doesn't do anything useful.
struct name {
type *lh_first; /* first element */
}


Missing semi-colon after struct definition.


Why use a struct?
#define LIST_ENTRY(type) See above.
struct {
type *le_next; /* next element */
type **le_prev; /* address of previous next element */

I suspect le_prev's comment is wrong. Surely le_prev is the previous
node in the list, not the previous le_next (which is /this/ node).
}

Questions:
Why the struct does not have a name?


Looks like an error to me.


This is the same as the original code.
Is the list a two-way list? Well there are pointers to both previous and next nodes...

/*
* List functions.
*/
#define LIST_INIT(head) {
(head)->lh_first = NULL;
}


That isn't how macros work. Read a textbook.

#define LIST_INSERT_AFTER(listelm, elm, field) {
if (((elm)->field.le_next = (listelm)->field.le_next) != NULL)
(listelm)->field.le_next->field.le_prev =
&(elm)->field.le_next;
(listelm)->field.le_next = (elm);
(elm)->field.le_prev = &(listelm)->field.le_next;
}

Question:
What is listelm, elm, field?

They're arguments to a function-style macro. Whoever wrote this doesn't
understand macros, and should be using functions instead.


I agree. I like function. But I have to use it. The three
arguements---listelm, elm and field confuse me.

#define LIST_INSERT_HEAD(head, elm, field) {
if (((elm)->field.le_next = (head)->lh_first) != NULL)
(head)->lh_first->field.le_prev =
&(elm)->field.le_next;
(head)->lh_first = (elm);
(elm)->field.le_prev = &(head)->lh_first;
}

Question:

If elm becomes head, what's the purpose of the last sentence:
(elm)->field.le_prev = &(head)->lh_first;

It is really confusing. What is (elm)->field?

How about using functions so we can see what the types of the arguments
are? If possible, post a compileable example.

HTH,
Jacques.

Jul 22 '05 #6
C++fan wrote:
Hi Jacques:

Thanks a lot.
The code is modified from /sys/queue.h of FreeBSD. Below is the link:
http://fxr.watson.org/fxr/source/sys/queue.h

The original code is from line 328 to 380. But I can not completely
understand it. It is confusing.


The slashes at the end of each line are not decoration. :-)
They join lines, so for example
#define MY_MACRO(x) \
((x)*2)
means
#define MY_MACRO(x) ((x)*2)

That's pretty ugly code, but they probably felt they had a good reason
at the time. The struct definitions could be used like this:

typedef LIST_ENTRY(foo) foo_entry;

which the preprocessor would turn into

typedef struct{
struct foo *le_next;
struct foo **le_prev
} foo_entry;

which is perfectly valid C (and C++).

Jul 22 '05 #7
By the way, is there any particular reason you're looking at the BSD
source? Or do you just like the deep end?

Jacques.

Jul 22 '05 #8
"C++fan" <jw****@excite.com> wrote in message
news:15**************************@posting.google.c om...
The following code is for list operation. But I can not understand.
Could anyone explain the code for me?

/*
* List definitions.
*/

#define LIST_HEAD(name, type)
struct name {
type *lh_first; /* first element */
}
#define LIST_ENTRY(type)
struct {
type *le_next; /* next element */
type **le_prev; /* address of previous next element */
}

Questions:
Why the struct does not have a name?
Is the list a two-way list?

/*
* List functions.
*/
#define LIST_INIT(head) {
(head)->lh_first = NULL;
}

#define LIST_INSERT_AFTER(listelm, elm, field) {
if (((elm)->field.le_next = (listelm)->field.le_next) != NULL)
(listelm)->field.le_next->field.le_prev =
&(elm)->field.le_next;
(listelm)->field.le_next = (elm);
(elm)->field.le_prev = &(listelm)->field.le_next;
}

Question:
What is listelm, elm, field?

#define LIST_INSERT_HEAD(head, elm, field) {
if (((elm)->field.le_next = (head)->lh_first) != NULL)
(head)->lh_first->field.le_prev =
&(elm)->field.le_next;
(head)->lh_first = (elm);
(elm)->field.le_prev = &(head)->lh_first;
}

Question:

If elm becomes head, what's the purpose of the last sentence:
(elm)->field.le_prev = &(head)->lh_first;
Thanks in advance.

Jack


Here is some tested code. I still hate it. :)

struct list_node
{
LIST_ENTRY(list_node) node;
int thing;
};

void list_test()
{
LIST_HEAD(t_head, list_node) mylist;
LIST_INIT(&mylist);
list_node *p1 = new list_node;
p1->thing = 24;
LIST_INSERT_HEAD(&mylist, p1, node);
list_node *p2 = new list_node;
p2->thing = -3;
LIST_INSERT_AFTER(p1, p2, node);

list_node *p3 = mylist.lh_first;
while (p3 != 0)
{
std::cout << p3->thing << '\n';
p3 = p3->node.le_next;
}

delete p2;
delete p1;
}

Output is:

24
-3

--
Cy
http://home.rochester.rr.com/cyhome/
Jul 22 '05 #9
Hi Cy:

Thank you very much. Your translation makes me understand more. But I
still have questions about your translation. Please look below.
By the way, I do not like the original code. But I have to use it. I
am studying NS2, which uses that code.

Regards,

Jack

"Cy Edmunds" <ce******@spamless.rochester.rr.com> wrote in message news:<3h****************@twister.nyroc.rr.com>...
"C++fan" <jw****@excite.com> wrote in message
news:15**************************@posting.google.c om...
The following code is for list operation. But I can not understand.
Could anyone explain the code for me?

/*
* List definitions.
*/

#define LIST_HEAD(name, type)
struct name {
type *lh_first; /* first element */
}
#define LIST_ENTRY(type)
struct {
type *le_next; /* next element */
type **le_prev; /* address of previous next element */
}

Questions:
Why the struct does not have a name?
Is the list a two-way list?

/*
* List functions.
*/
#define LIST_INIT(head) {
(head)->lh_first = NULL;
}

#define LIST_INSERT_AFTER(listelm, elm, field) {
if (((elm)->field.le_next = (listelm)->field.le_next) != NULL)
(listelm)->field.le_next->field.le_prev =
&(elm)->field.le_next;
(listelm)->field.le_next = (elm);
(elm)->field.le_prev = &(listelm)->field.le_next;
}

Question:
What is listelm, elm, field?

#define LIST_INSERT_HEAD(head, elm, field) {
if (((elm)->field.le_next = (head)->lh_first) != NULL)
(head)->lh_first->field.le_prev =
&(elm)->field.le_next;
(head)->lh_first = (elm);
(elm)->field.le_prev = &(head)->lh_first;
}

Question:

If elm becomes head, what's the purpose of the last sentence:
(elm)->field.le_prev = &(head)->lh_first;
Thanks in advance.

Jack
Jack, that's quite a puzzle. As a true "C++fan" I hope you won't actually
use crap like this unless you have to! (Hint: std::list)

Anyway, I'm far from sure of this but maybe it is used as follows:

struct fred_node
{
LIST_ENTRY(struct fred_node) node;
Fred fred; // Fred is some arbitrary type -- this is a list of Freds
};

which translates to:

struct fred_node
{
struct {
struct fred_node *le_next; /* next element */
struct fred_node **le_prev; /* address of previous next element */
} node;
Fred fred; // Fred is some arbitrary type -- this is a list of Freds
};

This defines the node type. Then make the list head:

LIST_HEAD(fred_head, struct fred_node) fredlist;
LIST_INIT(fredlist);

which is equivalent to:

struct fred_head {
struct fred_node *lh_first; /* first element */
} fredlist;
fredlist->lh_first = NULL;

Now add a node:

struct fred_node *new_node = (struct fred_node *) malloc(sizeof(struct
fred_node));
new_node.fred = Fred(21); // whatever that means
LIST_INSERT_HEAD(mylist, new_node, node);

which expands to

struct fred_node *new_node = (struct fred_node *) malloc(sizeof(struct
fred_node));
new_node.fred = Fred(21); // whatever that means
if ((new_node->node.le_next = (fredlist)->lh_first) != NULL)
fredlist->lh_first->node.le_prev = &new_node->node.le_next;
fredlist->lh_first = new_node;
new_node->node.le_prev = &new_node;


if ((new_node->node.le_next = (fredlist)->lh_first) != NULL)
It means the head is not NULL, right? So
fredlist->lh_first->node.le_prev should be NULL.
new_node->node.le_next should be NULL, since new_node is a new node.
So what is the meaning of:
fredlist->lh_first->node.le_prev = &new_node->node.le_next;

If head is NULL, (fredlist)->lh_first is NULL. the new_node becomes
the head.
What is the meaning of new_node->node.le_prev = &new_node; ?
Now add another node:

struct fred_node *newer_node = (struct fred_node *) malloc(sizeof(struct
fred_node));
newer_node.fred = Fred(-33); // whatever that means
LIST_INSERT_AFTER(newer_node, new_node, node);

which expands to:

struct fred_node *newer_node = (struct fred_node *) malloc(sizeof(struct
fred_node));
newer_node.fred = Fred(-33); // whatever that means
if ((new_node->node.le_next = newer_node->node.le_next) != NULL)
newer_node->node.le_next->node.le_prev = &new_node->node.le_next;
newer_node->node.le_next = new_node;
new_node->node.le_prev = &new_node;


Since newer_node is a new node, newer_node->node.le_next should be
NULL, right?
newer_node->node.le_next->node.le_prev equals to newer_node itself,
right?
Jul 22 '05 #10
Thanks Jacques. I am studying NS2, which uses that code.

Jack

Jacques Labuschagne <ja*****@clawshrimp.com> wrote in message news:<E9********************@news02.tsnz.net>...
By the way, is there any particular reason you're looking at the BSD
source? Or do you just like the deep end?

Jacques.

Jul 22 '05 #11
Thanks Jacques. What is the content of a node? Just two pointers,
le_next and le_prev?

Jack

Jacques Labuschagne <ja*****@clawshrimp.com> wrote in message news:<a4********************@news02.tsnz.net>...
C++fan wrote:
Hi Jacques:

Thanks a lot.
The code is modified from /sys/queue.h of FreeBSD. Below is the link:
http://fxr.watson.org/fxr/source/sys/queue.h

The original code is from line 328 to 380. But I can not completely
understand it. It is confusing.


The slashes at the end of each line are not decoration. :-)
They join lines, so for example
#define MY_MACRO(x) \
((x)*2)
means
#define MY_MACRO(x) ((x)*2)

That's pretty ugly code, but they probably felt they had a good reason
at the time. The struct definitions could be used like this:

typedef LIST_ENTRY(foo) foo_entry;

which the preprocessor would turn into

typedef struct{
struct foo *le_next;
struct foo **le_prev
} foo_entry;

which is perfectly valid C (and C++).

Jul 22 '05 #12
C++fan wrote:
Thanks Jacques. What is the content of a node? Just two pointers,
le_next and le_prev?


Yes. The LIST_HEAD macro gives you a structure with a pointer to a node,
and the LIST_ENTRY macro gives a struct with those two elements.

Here's an example:

struct my_type{
int value;
};

LIST_HEAD(head, my_type);
typedef LIST_ENTRY(my_type) entry;

After preprocessing this gives us

struct my_type{
int value;
};

struct head{
struct my_type *lh_first;
}
typedef struct{
struct my_type *le_next;
struct my_type **le_prev;
} entry;

Jul 22 '05 #13
"C++fan" <jw****@excite.com> wrote in message
news:15*************************@posting.google.co m...
Hi Cy:

Thank you very much. Your translation makes me understand more. But I
still have questions about your translation. Please look below.
By the way, I do not like the original code. But I have to use it. I
am studying NS2, which uses that code.

Regards,

Jack

[snip]

Jack, to tell you the truth I have invested about as much on this as I am
willing to. My suggestion is this: take the example I gave you and expand
all the macro calls manually. Then you will have a C++ program which should
not be too mysterious. Trying to look at the macro code directly would give
anybody a headache.

I figured you didn't like that code very much! As a programmer you do what
you have to do. I just didn't want to give the appearance of somehow
endorsing this monstrosity.

--
Cy
http://home.rochester.rr.com/cyhome/
Jul 22 '05 #14

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

4
by: John Dean | last post by:
Hi I have been reading quite a lot of Python source code recently and I have come across a particular construct which I don't understand. I would be grateful if somebody could explain the reason...
4
by: Chris | last post by:
Hello Could anyone explain why the following: #footer ul { float : left; margin : 2px 0px 7px 28px; padding : 0px; width : 360px;
3
by: Sid | last post by:
Hi folks, I wrote this code to test if I get the same address for all the variables in a union but for some reason the address I got when I used a char variable in a union seems bizarre- can...
6
by: B. Penn | last post by:
Hi, I was testing pointers and found that I could still dereference a pointer and access the value/variable it pointed to after deleting it, which confused me for "the variable it pointed to is...
21
by: Gactimus | last post by:
Can anyone explain what the lines with the '*' by them do? ----------- #ifndef _COUNTER_H #define _COUNTER_H #include <iostream> using namespace std; class Counter
20
by: ctyrrell | last post by:
Does anyone have any idea how to recover from a run-time error 3002 which I get after creating a workspace 242 times? Or better yet, avoid getting it in the first place? I am creating a...
1
by: Andrew | last post by:
Hello, friends, I am implementing web app security using asp.net 1.1, and I found the following source code from Yahoo! Mail login page: <form method="post"...
21
by: phpCodeHead | last post by:
Code which should allow my constructor to accept arguments: <?php class Person { function __construct($name) { $this->name = $name; } function getName()
4
by: Chuthu | last post by:
Could anyone explain me the following concepts in detail? 1. JAXP 2. BGRAPH 3. JBOSS work flow engine
0
by: Charles Arthur | last post by:
How do i turn on java script on a villaon, callus and itel keypad mobile phone
0
by: ryjfgjl | last post by:
If we have dozens or hundreds of excel to import into the database, if we use the excel import function provided by database editors such as navicat, it will be extremely tedious and time-consuming...
0
BarryA
by: BarryA | last post by:
What are the essential steps and strategies outlined in the Data Structures and Algorithms (DSA) roadmap for aspiring data scientists? How can individuals effectively utilize this roadmap to progress...
1
by: nemocccc | last post by:
hello, everyone, I want to develop a software for my android phone for daily needs, any suggestions?
0
by: Hystou | last post by:
There are some requirements for setting up RAID: 1. The motherboard and BIOS support RAID configuration. 2. The motherboard has 2 or more available SATA protocol SSD/HDD slots (including MSATA, M.2...
0
marktang
by: marktang | last post by:
ONU (Optical Network Unit) is one of the key components for providing high-speed Internet services. Its primary function is to act as an endpoint device located at the user's premises. However,...
0
by: Hystou | last post by:
Most computers default to English, but sometimes we require a different language, especially when relocating. Forgot to request a specific language before your computer shipped? No problem! You can...
0
jinu1996
by: jinu1996 | last post by:
In today's digital age, having a compelling online presence is paramount for businesses aiming to thrive in a competitive landscape. At the heart of this digital strategy lies an intricately woven...
0
by: Hystou | last post by:
Overview: Windows 11 and 10 have less user interface control over operating system update behaviour than previous versions of Windows. In Windows 11 and 10, there is no way to turn off the Windows...

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.