New double-linked list implementation, add death stats (kills always 0)
This commit is contained in:
parent
5e908b9936
commit
3f6d769ebe
11
bomber.h
11
bomber.h
@ -158,17 +158,6 @@ typedef struct generic {
|
||||
int data1,data2;
|
||||
} generic;
|
||||
|
||||
typedef union genericlistitem genericlistitem;
|
||||
union genericlistitem {
|
||||
listhead h;
|
||||
bomb b;
|
||||
flame f;
|
||||
brickdecay bc;
|
||||
player p;
|
||||
bonustile bt;
|
||||
generic g;
|
||||
};
|
||||
|
||||
enum tile_types {
|
||||
TILE_NONE = -1,
|
||||
TILE_DISEASE = 0,
|
||||
|
26
draw.c
26
draw.c
@ -53,7 +53,7 @@ int bigfontxsize,bigfontysize,bigfontyspace;
|
||||
|
||||
static int textx,texty;
|
||||
|
||||
static char *remapstring="0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ.:!?\177/\\*-,>< =";
|
||||
static const unsigned char *remapstring = (const unsigned char*) "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ.:!?\177/\\*-,>< =";
|
||||
static char asciiremap[256];
|
||||
|
||||
/* On screen array variables */
|
||||
@ -202,16 +202,16 @@ static void texthome(void) {
|
||||
textx=texty=10;
|
||||
}
|
||||
|
||||
// static void drawstring(int xpos,int ypos,char *str) {
|
||||
// char ch;
|
||||
//
|
||||
// while((ch=*str++)) {
|
||||
// drawfigure(xpos,ypos,font+asciiremap[toupper(ch)]);
|
||||
// xpos+=fontxsize;
|
||||
// }
|
||||
// }
|
||||
void drawstring(int xpos, int ypos, const char *str) {
|
||||
char ch;
|
||||
|
||||
void drawbigstring(int xpos,int ypos,char *str) {
|
||||
while((ch=*str++)) {
|
||||
drawfigure(xpos,ypos,font+asciiremap[toupper(ch)]);
|
||||
xpos+=fontxsize;
|
||||
}
|
||||
}
|
||||
|
||||
void drawbigstring(int xpos, int ypos, const char *str) {
|
||||
char ch;
|
||||
|
||||
while('\0' != (ch=*str++)) {
|
||||
@ -220,7 +220,7 @@ void drawbigstring(int xpos,int ypos,char *str) {
|
||||
}
|
||||
}
|
||||
|
||||
void centerbig(int y,char *str) {
|
||||
void centerbig(int y, const char *str) {
|
||||
int w;
|
||||
|
||||
w=strlen(str)*bigfontxsize;
|
||||
@ -363,7 +363,7 @@ int arraytoscreeny(int y) {
|
||||
|
||||
static void loadfonts(void) {
|
||||
int i,j;
|
||||
char *p;
|
||||
const unsigned char *p;
|
||||
|
||||
getsingle(fontname,font,NUMCHARACTERS);
|
||||
getsingle(bigfontname,bigfont,NUMCHARACTERS);
|
||||
@ -377,7 +377,7 @@ static void loadfonts(void) {
|
||||
memset(asciiremap,j,sizeof(asciiremap));
|
||||
p=remapstring;
|
||||
i=0;
|
||||
while(*p && i<40)
|
||||
while(*p && i<NUMCHARACTERS)
|
||||
asciiremap[(int)*p++]=i++;
|
||||
}
|
||||
|
||||
|
6
draw.h
6
draw.h
@ -3,9 +3,10 @@
|
||||
|
||||
void loadgfx(void);
|
||||
|
||||
void drawbigstring(int xpos,int ypos,char *str);
|
||||
void drawstring(int xpos, int ypos, const char *str);
|
||||
void drawbigstring(int xpos, int ypos, const char *str);
|
||||
|
||||
void centerbig(int y,char *str);
|
||||
void centerbig(int y, const char *str);
|
||||
|
||||
void addsprite(int x,int y,figure *fig);
|
||||
void plotsprites(void);
|
||||
@ -23,6 +24,7 @@ int arraytoscreeny(int y);
|
||||
|
||||
void failure(char *str,...);
|
||||
|
||||
extern int fontxsize,fontysize;
|
||||
extern int bigfontxsize,bigfontysize,bigfontyspace;
|
||||
|
||||
/* On screen array variables */
|
||||
|
111
game.c
111
game.c
@ -46,6 +46,8 @@ TILE_NONE,160
|
||||
|
||||
static GameOptions gameoptions;
|
||||
|
||||
static int host_kills, host_deaths;
|
||||
|
||||
static const unsigned char playerpositions[MAXNETNODES*3] = { /* color, x, y */
|
||||
2,0,0,
|
||||
3,14,10,
|
||||
@ -60,7 +62,7 @@ static const unsigned char playerpositions[MAXNETNODES*3] = { /* color, x, y */
|
||||
static void initplayer(int color,int x,int y,int controller) {
|
||||
player *pl;
|
||||
|
||||
pl=allocentry();
|
||||
pl = allocentry(player);
|
||||
if(!pl)
|
||||
nomem("Couldn't get player structure (allocentry())");
|
||||
addtail(&activeplayers,pl);
|
||||
@ -100,12 +102,22 @@ static void initplayers(void) {
|
||||
}
|
||||
}
|
||||
|
||||
static void resetstats(void) {
|
||||
int i;
|
||||
|
||||
host_deaths = host_kills = 0;
|
||||
for (i = 0; i < MAXNETNODES; i++) {
|
||||
netnodes[i].deaths = netnodes[i].kills = 0;
|
||||
}
|
||||
}
|
||||
|
||||
static void firstzero(void) {
|
||||
mycount = mydatacount = 0;
|
||||
memset(latestactions,0,sizeof(latestactions));
|
||||
memset(latestcounts,0,sizeof(latestcounts));
|
||||
memset(actionblock,0,sizeof(actionblock));
|
||||
actioncount = 0;
|
||||
resetstats();
|
||||
}
|
||||
|
||||
static void initgame() {
|
||||
@ -119,13 +131,13 @@ static void initgame() {
|
||||
set_game_options(&configopts);
|
||||
gameframe=0;
|
||||
allocthings();
|
||||
initheader(&activebombs);
|
||||
initheader(&detonatebombs);
|
||||
initheader(&activeflames);
|
||||
initheader(&activedecays);
|
||||
initheader(&activebonus);
|
||||
initheader(&activeplayers);
|
||||
initheader(&activegeneric);
|
||||
list_init_head(&activebombs);
|
||||
list_init_head(&detonatebombs);
|
||||
list_init_head(&activeflames);
|
||||
list_init_head(&activedecays);
|
||||
list_init_head(&activebonus);
|
||||
list_init_head(&activeplayers);
|
||||
list_init_head(&activegeneric);
|
||||
|
||||
p=bonuschances;
|
||||
bonustotal=0;
|
||||
@ -168,7 +180,7 @@ static void initgame() {
|
||||
static void addflame(player *owner,int px,int py) {
|
||||
flame *fl,*fl2;
|
||||
|
||||
fl=allocentry();
|
||||
fl = allocentry(flame);
|
||||
if(!fl) return;
|
||||
addtail(&activeflames,fl);
|
||||
field[py][px]=FIELD_FLAME;
|
||||
@ -204,7 +216,7 @@ static void dropbomb(player *pl,int px,int py,int type){
|
||||
bomb *bmb;
|
||||
|
||||
if(field[py][px]!=FIELD_EMPTY) return;
|
||||
bmb=allocentry();
|
||||
bmb = allocentry(bomb);
|
||||
if(!bmb) return;
|
||||
playsound(3);
|
||||
addtail(&activebombs,bmb);
|
||||
@ -225,7 +237,7 @@ static void adddecay(int px,int py) {
|
||||
brickdecay *bd;
|
||||
int xpos,ypos;
|
||||
|
||||
bd=allocentry();
|
||||
bd = allocentry(brickdecay);
|
||||
if(!bd) return;
|
||||
field[py][px]=FIELD_EXPLODING;
|
||||
bd->xpos=arraytoscreenx(px);
|
||||
@ -243,7 +255,7 @@ static void adddecay(int px,int py) {
|
||||
static void addbonus(int px,int py,int type) {
|
||||
bonustile *bonus;
|
||||
|
||||
bonus=allocentry();
|
||||
bonus = allocentry(bonustile);
|
||||
if(!bonus) return;
|
||||
addtail(&activebonus,bonus);
|
||||
bonus->px=px;
|
||||
@ -277,7 +289,8 @@ static void deletebonus(bonustile *bonus) {
|
||||
py=bonus->py;
|
||||
field[py][px]=0;
|
||||
info[py][px]=0;
|
||||
delink(bonus);
|
||||
list_del(&bonus->list);
|
||||
freeentry(bonus);
|
||||
}
|
||||
|
||||
static void adddetonate(bomb *bmb) {
|
||||
@ -294,7 +307,7 @@ static void adddetonate(bomb *bmb) {
|
||||
static void processbombs() {
|
||||
bomb *bmb, *next;
|
||||
|
||||
foreach_list_safe(&activebombs, bmb, next) {
|
||||
list_for_each_entry_safe(bmb, next, &activebombs, list) {
|
||||
++(bmb->figcount);
|
||||
++bmb->timer;
|
||||
switch(bmb->type) {
|
||||
@ -357,7 +370,8 @@ static void detonatebomb(bomb *bmb) {
|
||||
py=bmb->py;
|
||||
power=bmb->power;
|
||||
owner=bmb->owner;
|
||||
delink(bmb);
|
||||
list_del(&bmb->list);
|
||||
freeentry(bmb);
|
||||
addflame(owner,px,py);
|
||||
flameshaft(owner,px,py,-1,0,power);
|
||||
flameshaft(owner,px,py,0,-1,power);
|
||||
@ -380,13 +394,14 @@ static void dodetonations(void) {
|
||||
static void processflames(void) {
|
||||
flame *fl, *next;
|
||||
|
||||
foreach_list_safe(&activeflames, fl, next) {
|
||||
list_for_each_entry_safe(fl, next, &activeflames, list) {
|
||||
++(fl->timer);
|
||||
|
||||
if(fl->timer==FLAMELIFE) {
|
||||
field[fl->py][fl->px]=FIELD_EMPTY;
|
||||
info[fl->py][fl->px]=0;
|
||||
delink(fl);
|
||||
list_del(&fl->list);
|
||||
freeentry(fl);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -394,12 +409,13 @@ static void processflames(void) {
|
||||
static void processdecays() {
|
||||
brickdecay *bd, *next;
|
||||
|
||||
foreach_list_safe(&activedecays, bd, next) {
|
||||
list_for_each_entry_safe(bd, next, &activedecays, list) {
|
||||
++(bd->timer);
|
||||
if(bd->timer == DECAYLIFE) {
|
||||
field[bd->py][bd->px] = FIELD_EMPTY;
|
||||
trybonus(bd->px, bd->py);
|
||||
delink(bd);
|
||||
list_del(&bd->list);
|
||||
freeentry(bd);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -411,7 +427,7 @@ static void drawbombs(void) {
|
||||
int color;
|
||||
int xpos,ypos;
|
||||
|
||||
foreach_list_fast(&activebombs, bmb) {
|
||||
list_for_each_entry(bmb, &activebombs, list) {
|
||||
color=bmb->owner->color;
|
||||
figtab=(bmb->type==BOMB_NORMAL) ? bombs1[color] : bombs2[color];
|
||||
j=bmb->figcount % (NUMBOMBFRAMES<<1);
|
||||
@ -429,7 +445,7 @@ static void drawflames(void) {
|
||||
int color;
|
||||
int fig;
|
||||
|
||||
foreach_list_fast(&activeflames, fl) {
|
||||
list_for_each_entry(fl, &activeflames, list) {
|
||||
color=fl->owner->color;
|
||||
xpos=tovideox(fl->xpos);
|
||||
ypos=tovideoy(fl->ypos);
|
||||
@ -443,7 +459,7 @@ static void drawflames(void) {
|
||||
static void drawdecays() {
|
||||
brickdecay *bd;
|
||||
|
||||
foreach_list_fast(&activedecays, bd) {
|
||||
list_for_each_entry(bd, &activedecays, list) {
|
||||
addsprite(tovideox(bd->xpos),tovideoy(bd->ypos),
|
||||
blocksx+(bd->timer*9)/DECAYLIFE);
|
||||
}
|
||||
@ -452,7 +468,7 @@ static void drawdecays() {
|
||||
static void drawbonus() {
|
||||
bonustile *bonus;
|
||||
|
||||
foreach_list_fast(&activebonus, bonus) {
|
||||
list_for_each_entry(bonus, &activebonus, list) {
|
||||
addsprite(tovideox(bonus->xpos),tovideoy(bonus->ypos),
|
||||
tiles+bonus->type);
|
||||
}
|
||||
@ -462,7 +478,7 @@ static void drawplayers() {
|
||||
player *pl;
|
||||
int xpos,ypos;
|
||||
|
||||
foreach_list_fast(&activeplayers, pl) {
|
||||
list_for_each_entry(pl, &activeplayers, list) {
|
||||
if(!(pl->flags & FLG_DEAD)) {
|
||||
if(!pl->figure)
|
||||
pl->figure=walking[pl->color]+30;
|
||||
@ -476,15 +492,17 @@ static void drawplayers() {
|
||||
static void detonatecontrolled(player *pl) {
|
||||
bomb *bmb, *next;
|
||||
|
||||
foreach_list_safe(&activebombs, bmb, next) {
|
||||
list_for_each_entry_safe(bmb, next, &activebombs, list) {
|
||||
if(bmb->owner==pl && bmb->type==BOMB_CONTROLLED)
|
||||
adddetonate(bmb);
|
||||
}
|
||||
}
|
||||
|
||||
static void playonce(generic *gen) {
|
||||
if(gen->timer==gen->data1)
|
||||
delink(gen);
|
||||
if (gen->timer == gen->data1) {
|
||||
list_del(&gen->list);
|
||||
freeentry(gen);
|
||||
}
|
||||
}
|
||||
|
||||
static void drawgeneric(generic *gen) {
|
||||
@ -494,7 +512,7 @@ static void drawgeneric(generic *gen) {
|
||||
static void queuesequence(int xpos,int ypos,figure *fig,int count) {
|
||||
generic *gen;
|
||||
|
||||
gen=allocentry();
|
||||
gen = allocentry(generic);
|
||||
if(!gen) return;
|
||||
gen->xpos=xpos;
|
||||
gen->ypos=ypos;
|
||||
@ -514,6 +532,11 @@ static void adddeath(player *pl) {
|
||||
}
|
||||
|
||||
static void killplayer(player *pl) {
|
||||
if (pl->controller == -1) {
|
||||
host_deaths++;
|
||||
} else {
|
||||
netnodes[pl->controller].deaths++;
|
||||
}
|
||||
pl->flags|=FLG_DEAD;
|
||||
playsound(2);
|
||||
adddeath(pl);
|
||||
@ -523,7 +546,7 @@ static void killplayer(player *pl) {
|
||||
static void processgenerics(void) {
|
||||
generic *gen, *next;
|
||||
|
||||
foreach_list_safe(&activegeneric, gen, next) {
|
||||
list_for_each_entry_safe(gen, next, &activegeneric, list) {
|
||||
++(gen->timer);
|
||||
gen->process(gen);
|
||||
}
|
||||
@ -532,11 +555,34 @@ static void processgenerics(void) {
|
||||
static void drawgenerics(void) {
|
||||
generic *gen;
|
||||
|
||||
foreach_list_fast(&activegeneric, gen) {
|
||||
list_for_each_entry(gen, &activegeneric, list) {
|
||||
gen->draw(gen);
|
||||
}
|
||||
}
|
||||
|
||||
static void drawstats(void) {
|
||||
int d, k, p = 0, i;
|
||||
const char *n;
|
||||
char buf[16];
|
||||
|
||||
solidcopy(&background, 0, 0, IXSIZE, arraystarty);
|
||||
for (i = -1; i < MAXNETNODES; i++) {
|
||||
if (i >= 0) {
|
||||
if (!netnodes[i].used) continue;
|
||||
k = netnodes[i].kills;
|
||||
d = netnodes[i].deaths;
|
||||
n = netnodes[i].name;
|
||||
} else {
|
||||
k = host_kills;
|
||||
d = host_deaths;
|
||||
n = playername;
|
||||
}
|
||||
snprintf(buf, sizeof(buf), "%-8.8s %2i/%2i", n, k % 100, d % 100);
|
||||
drawstring(11 + (p/2) * (15 * fontxsize + 7), 11 + (p%2) * (fontysize+2), buf);
|
||||
p++;
|
||||
}
|
||||
}
|
||||
|
||||
static int centerxchange(player *pl) {
|
||||
int speed;
|
||||
int val;
|
||||
@ -764,7 +810,7 @@ static void doplayer(player *pl) {
|
||||
static void processplayers(void) {
|
||||
player *pl, *next;
|
||||
|
||||
foreach_list_safe(&activeplayers, pl, next) {
|
||||
list_for_each_entry_safe(pl, next, &activeplayers, list) {
|
||||
doplayer(pl);
|
||||
}
|
||||
}
|
||||
@ -850,6 +896,7 @@ static int iterate(void) {
|
||||
drawdecays();
|
||||
drawflames();
|
||||
drawplayers();
|
||||
drawstats();
|
||||
plotsprites();
|
||||
copyup();
|
||||
if (list_empty(&activegeneric)) {
|
||||
@ -858,7 +905,7 @@ static int iterate(void) {
|
||||
int deadplayers = 0;
|
||||
i = 0;
|
||||
|
||||
foreach_list_fast(&activeplayers, pl) {
|
||||
list_for_each_entry(pl, &activeplayers, list) {
|
||||
if(!(pl->flags & FLG_DEAD))
|
||||
++i;
|
||||
else
|
||||
|
45
list.c
45
list.c
@ -3,9 +3,20 @@
|
||||
#include "list.h"
|
||||
#include "utils.h"
|
||||
|
||||
typedef union genericlistitem genericlistitem;
|
||||
union genericlistitem {
|
||||
genericlistitem *next;
|
||||
bomb b;
|
||||
flame f;
|
||||
brickdecay bc;
|
||||
player p;
|
||||
bonustile bt;
|
||||
generic g;
|
||||
};
|
||||
|
||||
/* doesn't use prev link */
|
||||
static genericlistitem *things=0;
|
||||
static listhead *free_things;
|
||||
static genericlistitem *free_things;
|
||||
|
||||
void allocthings(void) {
|
||||
int i;
|
||||
@ -18,14 +29,16 @@ void allocthings(void) {
|
||||
}
|
||||
if(!things) nomem("Trying to allocate thing memory");
|
||||
for(i=0;i<num-1;++i) {
|
||||
things[i].h.next = (listhead*) &things[i+1];
|
||||
things[i].next = &things[i+1];
|
||||
}
|
||||
things[i].h.next = 0;
|
||||
free_things = (listhead*) things;
|
||||
things[i].next = 0;
|
||||
free_things = things;
|
||||
}
|
||||
|
||||
void *allocentry(void) {
|
||||
listhead *entry = free_things;
|
||||
void *_allocentry(size_t size) {
|
||||
genericlistitem *entry = free_things;
|
||||
|
||||
if (size > sizeof(genericlistitem)) return 0;
|
||||
|
||||
if (free_things) {
|
||||
free_things = free_things->next;
|
||||
@ -34,34 +47,26 @@ void *allocentry(void) {
|
||||
return entry;
|
||||
}
|
||||
|
||||
void _freeentry(listhead *entry) {
|
||||
void freeentry(void *ptr) {
|
||||
genericlistitem *entry = ptr;
|
||||
entry->next = free_things;
|
||||
entry->prev = NULL;
|
||||
free_things = entry;
|
||||
}
|
||||
|
||||
void _addtail(listhead *head, listhead *entry) {
|
||||
void list_add_tail(listhead *head, listhead *entry) {
|
||||
entry->next = head;
|
||||
entry->prev = head->prev;
|
||||
head->prev->next = entry;
|
||||
head->prev = entry;
|
||||
}
|
||||
|
||||
void _removeitem(listhead *entry) {
|
||||
void list_del(listhead *entry) {
|
||||
entry->next->prev = entry->prev;
|
||||
entry->prev->next = entry->next;
|
||||
entry->next = entry->prev = entry;
|
||||
}
|
||||
|
||||
listhead* delinkhead(listhead *entry) {
|
||||
listhead *result = entry->prev;
|
||||
|
||||
_removeitem(entry);
|
||||
_freeentry(entry);
|
||||
return result;
|
||||
}
|
||||
|
||||
void initheader(listhead *head) {
|
||||
void list_init_head(listhead *head) {
|
||||
head->next = head;
|
||||
head->prev = head;
|
||||
}
|
||||
|
||||
|
65
list.h
65
list.h
@ -1,32 +1,59 @@
|
||||
#ifndef LIST_H
|
||||
#define LIST_H
|
||||
|
||||
void allocthings(void);
|
||||
void *allocentry(void);
|
||||
void _freeentry(listhead *entry);
|
||||
#define freeentry(entry) _freeentry(&(entry->list));
|
||||
/* from linux kernel */
|
||||
|
||||
void _addtail(listhead *header, listhead *entry);
|
||||
#define addtail(head, entry) _addtail(head, &(entry->list));
|
||||
#define container_of(ptr, type, member) ({ \
|
||||
const typeof( ((type *)0)->member ) *__mptr = (ptr); \
|
||||
(type *)( (char *)__mptr - offsetof(type,member) );})
|
||||
|
||||
/**
|
||||
* list_entry - get the struct for this entry
|
||||
* @ptr: the &struct list_head pointer.
|
||||
* @type: the type of the struct this is embedded in.
|
||||
* @member: the name of the list_struct within the struct.
|
||||
*/
|
||||
#define list_entry(ptr, type, member) container_of(ptr, type, member)
|
||||
|
||||
void allocthings(void);
|
||||
void *_allocentry(size_t size);
|
||||
#define allocentry(type) (type*) _allocentry(sizeof(type))
|
||||
void freeentry(void *ptr);
|
||||
|
||||
void list_add_tail(listhead *header, listhead *entry);
|
||||
#define addtail(head, entry) list_add_tail(head, &(entry->list));
|
||||
|
||||
/* remove entry from list */
|
||||
void _removeitem(listhead *entry);
|
||||
#define removeitem(entry) _removeitem(&(entry->list));
|
||||
void list_del(listhead *entry);
|
||||
#define removeitem(entry) list_del(&(entry->list));
|
||||
|
||||
/* returns previous entry, deletes entry */
|
||||
listhead* delinkhead(listhead *entry);
|
||||
#define delink(entry) delinkhead(&(entry->list));
|
||||
void list_init_head(listhead *head);
|
||||
|
||||
|
||||
void initheader(listhead *head);
|
||||
/**
|
||||
* list_for_each_entry - iterate over list of given type
|
||||
* @pos: the type * to use as a loop cursor.
|
||||
* @head: the head for your list.
|
||||
* @member: the name of the list_struct within the struct.
|
||||
*/
|
||||
#define list_for_each_entry(pos, head, member) \
|
||||
for (pos = list_entry((head)->next, typeof(*pos), member); \
|
||||
/* prefetch(pos->member.next), */ \
|
||||
&pos->member != (head); \
|
||||
pos = list_entry(pos->member.next, typeof(*pos), member))
|
||||
|
||||
/* listhead *head, XXX *item */
|
||||
#define foreach_list_fast(head, item) \
|
||||
for (item = (void*) (head)->next; (listhead*) item != (head); item = (void*) ((listhead*)item)->next)
|
||||
|
||||
/* listhead *head, XXX *item, XXX *next : you are allowed to delink(item) */
|
||||
#define foreach_list_safe(head, item, next) \
|
||||
for (item = (void*) (head)->next, next = (void*) ((listhead*)item)->next; (listhead*) item != (head); item = next, next = (void*) ((listhead*)item)->next)
|
||||
/**
|
||||
* list_for_each_entry_safe - iterate over list of given type safe against removal of list entry
|
||||
* @pos:<-->the type * to use as a loop cursor.
|
||||
* @n:<><-->another type * to use as temporary storage
|
||||
* @head:<->the head for your list.
|
||||
* @member:>the name of the list_struct within the struct.
|
||||
*/
|
||||
#define list_for_each_entry_safe(pos, n, head, member) \
|
||||
for (pos = list_entry((head)->next, typeof(*pos), member), \
|
||||
n = list_entry(pos->member.next, typeof(*pos), member); \
|
||||
&pos->member != (head); \
|
||||
pos = n, n = list_entry(n->member.next, typeof(*n), member))
|
||||
|
||||
#define list_empty(head) ((head) == (head)->next)
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user