Print this page
new smatch

Split Close
Expand all
Collapse all
          --- old/usr/src/tools/smatch/src/ptrlist.h
          +++ new/usr/src/tools/smatch/src/ptrlist.h
   1    1  #ifndef PTR_LIST_H
   2    2  #define PTR_LIST_H
   3    3  
   4    4  #include <stdlib.h>
        5 +#include <stdbool.h>
   5    6  
   6    7  /*
   7    8   * Generic pointer list manipulation code. 
   8    9   *
   9   10   * (C) Copyright Linus Torvalds 2003-2005
  10   11   */
  11   12  
  12   13  /* Silly type-safety check ;) */
  13      -#define DECLARE_PTR_LIST(listname,type) struct listname { type *list[1]; }
  14   14  #define CHECK_TYPE(head,ptr)            (void)(&(ptr) == &(head)->list[0])
  15   15  #define TYPEOF(head)                    __typeof__(&(head)->list[0])
  16   16  #define VRFY_PTR_LIST(head)             (void)(sizeof((head)->list[0]))
  17   17  
  18      -/*
  19      - * The "unnecessary" statement expression is there to shut up a totally 
  20      - * bogus gcc warning about unused expressions, brought on by the fact
  21      - * that we cast the result to the proper type.
  22      - */
  23      -#define MKTYPE(head,expr)               ({ (TYPEOF(head))(expr); })
       18 +#define LIST_NODE_NR (13)
  24   19  
  25      -#define LIST_NODE_NR (29)
       20 +#define DECLARE_PTR_LIST(listname, type)        \
       21 +        struct listname {                       \
       22 +                int nr:8;                       \
       23 +                int rm:8;                       \
       24 +                struct listname *prev;          \
       25 +                struct listname *next;          \
       26 +                type *list[LIST_NODE_NR];       \
       27 +        }
  26   28  
  27      -struct ptr_list {
  28      -        int nr:8;
  29      -        int rm:8;
  30      -        struct ptr_list *prev;
  31      -        struct ptr_list *next;
  32      -        void *list[LIST_NODE_NR];
  33      -};
       29 +DECLARE_PTR_LIST(ptr_list, void);
  34   30  
  35      -#define ptr_list_empty(x) ((x) == NULL)
  36   31  
  37   32  void * undo_ptr_list_last(struct ptr_list **head);
  38   33  void * delete_ptr_list_last(struct ptr_list **head);
  39   34  int delete_ptr_list_entry(struct ptr_list **, void *, int);
  40   35  int replace_ptr_list_entry(struct ptr_list **, void *old, void *new, int);
       36 +bool lookup_ptr_list_entry(const struct ptr_list *head, const void *entry);
  41   37  extern void sort_list(struct ptr_list **, int (*)(const void *, const void *));
  42   38  
  43      -extern void **__add_ptr_list(struct ptr_list **, void *, unsigned long);
  44   39  extern void concat_ptr_list(struct ptr_list *a, struct ptr_list **b);
  45      -extern void __free_ptr_list(struct ptr_list **);
       40 +extern void copy_ptr_list(struct ptr_list **h, struct ptr_list *t);
  46   41  extern int ptr_list_size(struct ptr_list *);
       42 +extern bool ptr_list_empty(const struct ptr_list *head);
       43 +extern bool ptr_list_multiple(const struct ptr_list *head);
  47   44  extern int linearize_ptr_list(struct ptr_list *, void **, int);
       45 +extern void *first_ptr_list(struct ptr_list *);
       46 +extern void *last_ptr_list(struct ptr_list *);
       47 +extern void *ptr_list_nth_entry(struct ptr_list *, unsigned int idx);
       48 +extern void pack_ptr_list(struct ptr_list **);
  48   49  
  49   50  /*
  50   51   * Hey, who said that you can't do overloading in C?
  51   52   *
  52   53   * You just have to be creative, and use some gcc
  53   54   * extensions..
  54   55   */
  55      -#define add_ptr_list_tag(list,entry,tag) \
  56      -        MKTYPE(*(list), (CHECK_TYPE(*(list),(entry)),__add_ptr_list((struct ptr_list **)(list), (entry), (tag))))
  57      -#define add_ptr_list_notag(list,entry)                                                                          \
  58      -        MKTYPE(*(list), (CHECK_TYPE(*(list),(entry)),__add_ptr_list((struct ptr_list **)(list),                 \
  59      -                                                                    (void *)((unsigned long)(entry) & ~3UL),    \
  60      -                                                                    (unsigned long)(entry) & 3)))
  61      -#define add_ptr_list(list,entry) \
  62      -        add_ptr_list_tag(list,entry,0)
  63      -#define free_ptr_list(list) \
  64      -        do { VRFY_PTR_LIST(*(list)); __free_ptr_list((struct ptr_list **)(list)); } while (0)
       56 +extern void **__add_ptr_list(struct ptr_list **, void *);
       57 +extern void **__add_ptr_list_tag(struct ptr_list **, void *, unsigned long);
  65   58  
  66      -#define PTR_ENTRY_NOTAG(h,i)    ((h)->list[i])
  67      -#define PTR_ENTRY(h,i)  (void *)(~3UL & (unsigned long)PTR_ENTRY_NOTAG(h,i))
       59 +#define add_ptr_list(list, ptr) ({                                      \
       60 +                struct ptr_list** head = (struct ptr_list**)(list);     \
       61 +                CHECK_TYPE(*(list),ptr);                                \
       62 +                (__typeof__(&(ptr))) __add_ptr_list(head, ptr);         \
       63 +        })
       64 +#define add_ptr_list_tag(list, ptr, tag) ({                             \
       65 +                struct ptr_list** head = (struct ptr_list**)(list);     \
       66 +                CHECK_TYPE(*(list),ptr);                                \
       67 +                (__typeof__(&(ptr))) __add_ptr_list_tag(head, ptr, tag);\
       68 +        })
  68   69  
  69      -static inline void *first_ptr_list(struct ptr_list *list)
  70      -{
  71      -        struct ptr_list *head = list;
       70 +extern void __free_ptr_list(struct ptr_list **);
       71 +#define free_ptr_list(list)     do {                                    \
       72 +                VRFY_PTR_LIST(*(list));                                 \
       73 +                __free_ptr_list((struct ptr_list **)(list));            \
       74 +        } while (0)
  72   75  
  73      -        if (!list)
  74      -                return NULL;
  75   76  
  76      -        while (list->nr == 0) {
  77      -                list = list->next;
  78      -                if (list == head)
  79      -                        return NULL;
  80      -        }
  81      -        return PTR_ENTRY(list, 0);
  82      -}
       77 +////////////////////////////////////////////////////////////////////////
       78 +// API
       79 +#define PREPARE_PTR_LIST(head, ptr) \
       80 +        DO_PREPARE(head, ptr, __head##ptr, __list##ptr, __nr##ptr, PTR_ENTRY_UNTAG)
  83   81  
  84      -static inline void *last_ptr_list(struct ptr_list *list)
  85      -{
  86      -        struct ptr_list *head = list;
       82 +#define NEXT_PTR_LIST(ptr) \
       83 +        DO_NEXT(ptr, __head##ptr, __list##ptr, __nr##ptr, PTR_ENTRY_UNTAG)
  87   84  
  88      -        if (!list)
  89      -                return NULL;
  90      -        list = list->prev;
  91      -        while (list->nr == 0) {
  92      -                if (list == head)
  93      -                        return NULL;
  94      -                list = list->prev;
  95      -        }
  96      -        return PTR_ENTRY(list, list->nr-1);
  97      -}
       85 +#define RESET_PTR_LIST(ptr) \
       86 +        DO_RESET(ptr, __head##ptr, __list##ptr, __nr##ptr, PTR_ENTRY_UNTAG)
  98   87  
  99      -#define PTR_DEREF(__head, idx, PTR_ENTRY) ({                                            \
 100      -        struct ptr_list *__list = __head;                                               \
 101      -        while (__list && __list->nr == 0) {                                             \
 102      -                __list = __list->next;                                                  \
 103      -                if (__list == __head)                                                   \
 104      -                        __list = NULL;                                                  \
 105      -        }                                                                               \
 106      -        __list ? PTR_ENTRY(__list, idx) : NULL;                                         \
 107      -})
       88 +#define FINISH_PTR_LIST(ptr) \
       89 +        DO_FINISH(ptr, __head##ptr, __list##ptr, __nr##ptr)
 108   90  
 109      -#define DO_PREPARE(head, ptr, __head, __list, __nr, PTR_ENTRY)                          \
 110      -        do {                                                                            \
 111      -                struct ptr_list *__head = (struct ptr_list *) (head);                   \
 112      -                struct ptr_list *__list = __head;                                       \
 113      -                int __nr = 0;                                                           \
 114      -                CHECK_TYPE(head,ptr);                                                   \
 115      -                ptr = PTR_DEREF(__head, 0, PTR_ENTRY);                                  \
       91 +#define RECURSE_PTR_REVERSE(ptr, new)                                   \
       92 +        DO_REVERSE(ptr, __head##ptr, __list##ptr, __nr##ptr,            \
       93 +                   new, __head##new, __list##new, __nr##new, PTR_ENTRY_UNTAG)
 116   94  
 117      -#define DO_NEXT(ptr, __head, __list, __nr, PTR_ENTRY)                                   \
 118      -                if (ptr) {                                                              \
 119      -                        if (++__nr < __list->nr) {                                      \
 120      -                                ptr = PTR_ENTRY(__list,__nr);                           \
 121      -                        } else {                                                        \
 122      -                                __list = __list->next;                                  \
 123      -                                ptr = NULL;                                             \
 124      -                                while (__list->nr == 0 && __list != __head)             \
 125      -                                        __list = __list->next;                          \
 126      -                                if (__list != __head) {                                 \
 127      -                                        __nr = 0;                                       \
 128      -                                        ptr = PTR_ENTRY(__list,0);                      \
 129      -                                }                                                       \
 130      -                        }                                                               \
 131      -                }
 132   95  
 133      -#define DO_RESET(ptr, __head, __list, __nr, PTR_ENTRY)                                  \
 134      -        do {                                                                            \
 135      -                __nr = 0;                                                               \
 136      -                __list = __head;                                                        \
 137      -                if (__head) ptr = PTR_DEREF(__head, 0, PTR_ENTRY);                      \
 138      -        } while (0)
       96 +#define FOR_EACH_PTR(head, ptr) \
       97 +        DO_FOR_EACH(head, ptr, __head##ptr, __list##ptr, __nr##ptr, PTR_ENTRY_NOTAG)
 139   98  
 140      -#define DO_FINISH(ptr, __head, __list, __nr)                                            \
 141      -                (void)(__nr); /* Sanity-check nesting */                                \
 142      -        } while (0)
       99 +#define FOR_EACH_PTR_TAG(head, ptr) \
      100 +        DO_FOR_EACH(head, ptr, __head##ptr, __list##ptr, __nr##ptr, PTR_ENTRY_UNTAG)
 143  101  
 144      -#define PREPARE_PTR_LIST(head, ptr) \
 145      -        DO_PREPARE(head, ptr, __head##ptr, __list##ptr, __nr##ptr, PTR_ENTRY)
      102 +#define END_FOR_EACH_PTR(ptr) \
      103 +        DO_END_FOR_EACH(ptr, __head##ptr, __list##ptr, __nr##ptr)
 146  104  
 147      -#define NEXT_PTR_LIST(ptr) \
 148      -        DO_NEXT(ptr, __head##ptr, __list##ptr, __nr##ptr, PTR_ENTRY)
      105 +#define FOR_EACH_PTR_REVERSE(head, ptr) \
      106 +        DO_FOR_EACH_REVERSE(head, ptr, __head##ptr, __list##ptr, __nr##ptr, PTR_ENTRY_NOTAG)
 149  107  
 150      -#define RESET_PTR_LIST(ptr) \
 151      -        DO_RESET(ptr, __head##ptr, __list##ptr, __nr##ptr, PTR_ENTRY)
      108 +#define FOR_EACH_PTR_REVERSE_TAG(head, ptr) \
      109 +        DO_FOR_EACH_REVERSE(head, ptr, __head##ptr, __list##ptr, __nr##ptr, PTR_ENTRY_UNTAG)
 152  110  
 153      -#define FINISH_PTR_LIST(ptr) \
 154      -        DO_FINISH(ptr, __head##ptr, __list##ptr, __nr##ptr)
      111 +#define END_FOR_EACH_PTR_REVERSE(ptr) \
      112 +        DO_END_FOR_EACH_REVERSE(ptr, __head##ptr, __list##ptr, __nr##ptr)
 155  113  
 156      -#define DO_FOR_EACH(head, ptr, __head, __list, __nr, PTR_ENTRY) do {                    \
 157      -        struct ptr_list *__head = (struct ptr_list *) (head);                           \
 158      -        struct ptr_list *__list = __head;                                               \
 159      -        CHECK_TYPE(head,ptr);                                                           \
 160      -        if (__head) {                                                                   \
 161      -                do { int __nr;                                                          \
 162      -                        for (__nr = 0; __nr < __list->nr; __nr++) {                     \
 163      -                                do {                                                    \
 164      -                                        ptr = PTR_ENTRY(__list,__nr);                   \
 165      -                                        if (__list->rm && !ptr)                         \
 166      -                                                continue;                               \
 167      -                                        do {
      114 +#define THIS_ADDRESS(ptr) \
      115 +        DO_THIS_ADDRESS(ptr, __head##ptr, __list##ptr, __nr##ptr)
 168  116  
 169      -#define DO_END_FOR_EACH(ptr, __head, __list, __nr)                                      \
 170      -                                        } while (0);                                    \
 171      -                                } while (0);                                            \
 172      -                        }                                                               \
 173      -                } while ((__list = __list->next) != __head);                            \
 174      -        }                                                                               \
 175      -} while (0)
      117 +#define INSERT_CURRENT(new, ptr) \
      118 +        DO_INSERT_CURRENT(new, __head##ptr, __list##ptr, __nr##ptr)
 176  119  
 177      -#define DO_FOR_EACH_REVERSE(head, ptr, __head, __list, __nr, PTR_ENTRY) do {            \
 178      -        struct ptr_list *__head = (struct ptr_list *) (head);                           \
 179      -        struct ptr_list *__list = __head;                                               \
 180      -        CHECK_TYPE(head,ptr);                                                           \
 181      -        if (__head) {                                                                   \
 182      -                do { int __nr;                                                          \
 183      -                        __list = __list->prev;                                          \
 184      -                        __nr = __list->nr;                                              \
 185      -                        while (--__nr >= 0) {                                           \
 186      -                                do {                                                    \
 187      -                                        ptr = PTR_ENTRY(__list,__nr);                   \
 188      -                                        if (__list->rm && !ptr)                         \
 189      -                                                continue;                               \
 190      -                                        do {
      120 +#define DELETE_CURRENT_PTR(ptr) \
      121 +        DO_DELETE_CURRENT(__head##ptr, __list##ptr, __nr##ptr)
 191  122  
      123 +#define REPLACE_CURRENT_PTR(ptr, new_ptr)                               \
      124 +        do { *THIS_ADDRESS(ptr) = (new_ptr); } while (0)
 192  125  
 193      -#define DO_END_FOR_EACH_REVERSE(ptr, __head, __list, __nr)                              \
 194      -                                        } while (0);                                    \
 195      -                                } while (0);                                            \
 196      -                        }                                                               \
 197      -                } while (__list != __head);                                             \
 198      -        }                                                                               \
 199      -} while (0)
      126 +// This replace the current element by a null-pointer.
      127 +// It's used when an element of the list must be removed
      128 +// but the address of the other elements must not be changed.
      129 +#define MARK_CURRENT_DELETED(ptr) \
      130 +        DO_MARK_CURRENT_DELETED(ptr, __list##ptr)
 200  131  
 201      -#define DO_REVERSE(ptr, __head, __list, __nr, new, __newhead,                           \
 202      -                   __newlist, __newnr, PTR_ENTRY) do {                                  \
 203      -        struct ptr_list *__newhead = __head;                                            \
 204      -        struct ptr_list *__newlist = __list;                                            \
 205      -        int __newnr = __nr;                                                             \
 206      -        new = ptr;                                                                      \
 207      -        goto __inside##new;                                                             \
 208      -        if (1) {                                                                        \
 209      -                do {                                                                    \
 210      -                        __newlist = __newlist->prev;                                    \
 211      -                        __newnr = __newlist->nr;                                        \
 212      -        __inside##new:                                                                  \
 213      -                        while (--__newnr >= 0) {                                        \
 214      -                                do {                                                    \
 215      -                                        new = PTR_ENTRY(__newlist,__newnr);             \
 216      -                                        do {
      132 +#define PACK_PTR_LIST(x) \
      133 +        pack_ptr_list((struct ptr_list **)(x))
 217  134  
 218      -#define RECURSE_PTR_REVERSE(ptr, new)                                                   \
 219      -        DO_REVERSE(ptr, __head##ptr, __list##ptr, __nr##ptr,                            \
 220      -                   new, __head##new, __list##new, __nr##new, PTR_ENTRY)
      135 +#define CURRENT_TAG(ptr)        (3 & (unsigned long)*THIS_ADDRESS(ptr))
      136 +#define TAG_CURRENT(ptr,val)    update_tag(THIS_ADDRESS(ptr),val)
 221  137  
 222      -#define DO_THIS_ADDRESS(ptr, __head, __list, __nr)                                      \
 223      -        ((__typeof__(&(ptr))) (__list->list + __nr))
      138 +// backward compatibility for smatch
      139 +#define FOR_EACH_PTR_NOTAG(list, ptr)   FOR_EACH_PTR(list, ptr)
      140 +#define END_FOR_EACH_PTR_NOTAG(ptr)     END_FOR_EACH_PTR(ptr)
 224  141  
 225      -#define FOR_EACH_PTR(head, ptr) \
 226      -        DO_FOR_EACH(head, ptr, __head##ptr, __list##ptr, __nr##ptr, PTR_ENTRY)
      142 +////////////////////////////////////////////////////////////////////////
      143 +// Implementation
      144 +#define PTR_UNTAG(p)            ((void*)(~3UL & (unsigned long)(p)))
      145 +#define PTR_ENTRY_NOTAG(h,i)    ((h)->list[i])
      146 +#define PTR_ENTRY_UNTAG(h,i)    PTR_UNTAG((h)->list[i])
 227  147  
 228      -#define END_FOR_EACH_PTR(ptr) \
 229      -        DO_END_FOR_EACH(ptr, __head##ptr, __list##ptr, __nr##ptr)
 230  148  
 231      -#define FOR_EACH_PTR_NOTAG(head, ptr) \
 232      -        DO_FOR_EACH(head, ptr, __head##ptr, __list##ptr, __nr##ptr, PTR_ENTRY_NOTAG)
      149 +#define PTR_NEXT(ptr, __head, __list, __nr, PTR_ENTRY)                  \
      150 +        do {                                                            \
      151 +                if (__nr < __list->nr) {                                \
      152 +                        ptr = PTR_ENTRY(__list,__nr);                   \
      153 +                        __nr++;                                         \
      154 +                        break;                                          \
      155 +                }                                                       \
      156 +                ptr = NULL;                                             \
      157 +                __nr = 0;                                               \
      158 +        } while ((__list = __list->next) != __head)                     \
 233  159  
 234      -#define END_FOR_EACH_PTR_NOTAG(ptr) END_FOR_EACH_PTR(ptr)
      160 +#define DO_PREPARE(head, ptr, __head, __list, __nr, PTR_ENTRY)          \
      161 +        do {                                                            \
      162 +                __typeof__(head) __head = (head);                       \
      163 +                __typeof__(head) __list = __head;                       \
      164 +                int __nr = 0;                                           \
      165 +                ptr = NULL;                                             \
      166 +                if (__head) {                                           \
      167 +                        PTR_NEXT(ptr, __head, __list, __nr, PTR_ENTRY); \
      168 +                }                                                       \
 235  169  
 236      -#define FOR_EACH_PTR_REVERSE(head, ptr) \
 237      -        DO_FOR_EACH_REVERSE(head, ptr, __head##ptr, __list##ptr, __nr##ptr, PTR_ENTRY)
      170 +#define DO_NEXT(ptr, __head, __list, __nr, PTR_ENTRY)                   \
      171 +                if (ptr) {                                              \
      172 +                        PTR_NEXT(ptr, __head, __list, __nr, PTR_ENTRY); \
      173 +                }
 238  174  
 239      -#define END_FOR_EACH_PTR_REVERSE(ptr) \
 240      -        DO_END_FOR_EACH_REVERSE(ptr, __head##ptr, __list##ptr, __nr##ptr)
      175 +#define DO_RESET(ptr, __head, __list, __nr, PTR_ENTRY)                  \
      176 +        do {                                                            \
      177 +                __nr = 0;                                               \
      178 +                __list = __head;                                        \
      179 +                if (__head)                                             \
      180 +                        PTR_NEXT(ptr, __head, __list, __nr, PTR_ENTRY); \
      181 +        } while (0)
 241  182  
 242      -#define FOR_EACH_PTR_REVERSE_NOTAG(head, ptr) \
 243      -        DO_FOR_EACH_REVERSE(head, ptr, __head##ptr, __list##ptr, __nr##ptr, PTR_ENTRY_NOTAG)
      183 +#define DO_FINISH(ptr, __head, __list, __nr)                            \
      184 +                VRFY_PTR_LIST(__head); /* Sanity-check nesting */       \
      185 +        } while (0)
 244  186  
 245      -#define END_FOR_EACH_PTR_REVERSE_NOTAG(ptr) END_FOR_EACH_PTR_REVERSE(ptr)
      187 +#define DO_FOR_EACH(head, ptr, __head, __list, __nr, PTR_ENTRY) do {    \
      188 +        __typeof__(head) __head = (head);                               \
      189 +        __typeof__(head) __list = __head;                               \
      190 +        int __nr;                                                       \
      191 +        if (!__head)                                                    \
      192 +                break;                                                  \
      193 +        do {                                                            \
      194 +                for (__nr = 0; __nr < __list->nr; __nr++) {             \
      195 +                        ptr = PTR_ENTRY(__list,__nr);                   \
      196 +                        if (__list->rm && !ptr)                         \
      197 +                                continue;                               \
 246  198  
 247      -#define THIS_ADDRESS(ptr) \
 248      -        DO_THIS_ADDRESS(ptr, __head##ptr, __list##ptr, __nr##ptr)
      199 +#define DO_END_FOR_EACH(ptr, __head, __list, __nr)                      \
      200 +                }                                                       \
      201 +        } while ((__list = __list->next) != __head);                    \
      202 +} while (0)
 249  203  
 250      -extern void split_ptr_list_head(struct ptr_list *);
      204 +#define DO_FOR_EACH_REVERSE(head, ptr, __head, __list, __nr, PTR_ENTRY) do { \
      205 +        __typeof__(head) __head = (head);                               \
      206 +        __typeof__(head) __list = __head;                               \
      207 +        int __nr;                                                       \
      208 +        if (!head)                                                      \
      209 +                break;                                                  \
      210 +        do {                                                            \
      211 +                __list = __list->prev;                                  \
      212 +                __nr = __list->nr;                                      \
      213 +                while (--__nr >= 0) {                                   \
      214 +                        ptr = PTR_ENTRY(__list,__nr);                   \
      215 +                        if (__list->rm && !ptr)                         \
      216 +                                continue;                               \
 251  217  
 252      -#define DO_SPLIT(ptr, __head, __list, __nr) do {                                        \
 253      -        split_ptr_list_head(__list);                                                    \
 254      -        if (__nr >= __list->nr) {                                                       \
 255      -                __nr -= __list->nr;                                                     \
 256      -                __list = __list->next;                                                  \
 257      -        };                                                                              \
 258      -} while (0)
 259  218  
 260      -#define DO_INSERT_CURRENT(new, ptr, __head, __list, __nr) do {                          \
 261      -        void **__this, **__last;                                                        \
 262      -        if (__list->nr == LIST_NODE_NR)                                                 \
 263      -                DO_SPLIT(ptr, __head, __list, __nr);                                    \
 264      -        __this = __list->list + __nr;                                                   \
 265      -        __last = __list->list + __list->nr - 1;                                         \
 266      -        while (__last >= __this) {                                                      \
 267      -                __last[1] = __last[0];                                                  \
 268      -                __last--;                                                               \
 269      -        }                                                                               \
 270      -        *__this = (new);                                                                \
 271      -        __list->nr++;                                                                   \
      219 +#define DO_END_FOR_EACH_REVERSE(ptr, __head, __list, __nr)              \
      220 +                }                                                       \
      221 +        } while (__list != __head);                                     \
 272  222  } while (0)
 273  223  
 274      -#define INSERT_CURRENT(new, ptr) \
 275      -        DO_INSERT_CURRENT(new, ptr, __head##ptr, __list##ptr, __nr##ptr)
      224 +#define DO_REVERSE(ptr, __head, __list, __nr, new, __newhead,           \
      225 +                   __newlist, __newnr, PTR_ENTRY) do {                  \
      226 +        __typeof__(__head) __newhead = __head;                          \
      227 +        __typeof__(__head) __newlist = __list;                          \
      228 +        int __newnr = __nr;                                             \
      229 +        new = ptr;                                                      \
      230 +        goto __inside##new;                                             \
      231 +        do {                                                            \
      232 +                __newlist = __newlist->prev;                            \
      233 +                __newnr = __newlist->nr;                                \
      234 +        __inside##new:                                                  \
      235 +                while (--__newnr >= 0) {                                \
      236 +                        new = PTR_ENTRY(__newlist,__newnr);             \
 276  237  
 277      -#define DO_DELETE_CURRENT(ptr, __head, __list, __nr) do {                               \
 278      -        void **__this = __list->list + __nr;                                            \
 279      -        void **__last = __list->list + __list->nr - 1;                                  \
 280      -        while (__this < __last) {                                                       \
 281      -                __this[0] = __this[1];                                                  \
 282      -                __this++;                                                               \
 283      -        }                                                                               \
 284      -        *__this = (void *)0xf0f0f0f0;                                                   \
 285      -        __list->nr--; __nr--;                                                           \
 286      -} while (0)
      238 +#define DO_THIS_ADDRESS(ptr, __head, __list, __nr)                      \
      239 +        (&__list->list[__nr])
 287  240  
 288      -#define DELETE_CURRENT_PTR(ptr) \
 289      -        DO_DELETE_CURRENT(ptr, __head##ptr, __list##ptr, __nr##ptr)
 290  241  
 291      -#define REPLACE_CURRENT_PTR(ptr, new_ptr)                                               \
 292      -        do { *THIS_ADDRESS(ptr) = (new_ptr); } while (0)
      242 +extern void split_ptr_list_head(struct ptr_list *);
 293  243  
 294      -#define DO_MARK_CURRENT_DELETED(ptr, __list) do {       \
 295      -                REPLACE_CURRENT_PTR(ptr, NULL);         \
 296      -                __list->rm++;                           \
 297      -        } while (0)
      244 +#define DO_INSERT_CURRENT(new, __head, __list, __nr) do {               \
      245 +        TYPEOF(__head) __this, __last;                                  \
      246 +        if (__list->nr == LIST_NODE_NR) {                               \
      247 +                split_ptr_list_head((struct ptr_list*)__list);          \
      248 +                if (__nr >= __list->nr) {                               \
      249 +                        __nr -= __list->nr;                             \
      250 +                        __list = __list->next;                          \
      251 +                }                                                       \
      252 +        }                                                               \
      253 +        __this = __list->list + __nr;                                   \
      254 +        __last = __list->list + __list->nr - 1;                         \
      255 +        while (__last >= __this) {                                      \
      256 +                __last[1] = __last[0];                                  \
      257 +                __last--;                                               \
      258 +        }                                                               \
      259 +        *__this = (new);                                                \
      260 +        __list->nr++;                                                   \
      261 +} while (0)
 298  262  
 299      -#define MARK_CURRENT_DELETED(ptr) \
 300      -        DO_MARK_CURRENT_DELETED(ptr, __list##ptr)
      263 +#define DO_DELETE_CURRENT(__head, __list, __nr) do {                    \
      264 +        TYPEOF(__head) __this = __list->list + __nr;                    \
      265 +        TYPEOF(__head) __last = __list->list + __list->nr - 1;          \
      266 +        while (__this < __last) {                                       \
      267 +                __this[0] = __this[1];                                  \
      268 +                __this++;                                               \
      269 +        }                                                               \
      270 +        *__this = (void *)0xf0f0f0f0;                                   \
      271 +        __list->nr--; __nr--;                                           \
      272 +} while (0)
 301  273  
 302      -extern void pack_ptr_list(struct ptr_list **);
 303  274  
 304      -#define PACK_PTR_LIST(x) pack_ptr_list((struct ptr_list **)(x))
      275 +#define DO_MARK_CURRENT_DELETED(ptr, __list) do {                       \
      276 +                REPLACE_CURRENT_PTR(ptr, NULL);                         \
      277 +                __list->rm++;                                           \
      278 +        } while (0)
 305  279  
      280 +
 306  281  static inline void update_tag(void *p, unsigned long tag)
 307  282  {
 308  283          unsigned long *ptr = p;
 309  284          *ptr = tag | (~3UL & *ptr);
 310  285  }
 311  286  
 312  287  static inline void *tag_ptr(void *ptr, unsigned long tag)
 313  288  {
 314  289          return (void *)(tag | (unsigned long)ptr);
 315  290  }
 316  291  
 317      -#define CURRENT_TAG(ptr) (3 & (unsigned long)*THIS_ADDRESS(ptr))
 318      -#define TAG_CURRENT(ptr,val)    update_tag(THIS_ADDRESS(ptr),val)
 319      -
 320  292  #endif /* PTR_LIST_H */
    
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX