r600g: Enable GL_ARB_gpu_shader5 extension
[mesa.git] / src / glsl / list.h
index 922bd68ab5ee4e8c4ac3860de2d05892eba42165..15fcd4abd1c486ded6e39a049c27a7fc60e1b32c 100644 (file)
  * Therefore, if \c head->next is \c NULL or \c tail_prev->prev is \c NULL,
  * the list is empty.
  *
+ * Do note that this means that the list nodes will contain pointers into the
+ * list structure itself and as a result you may not \c realloc() an  \c
+ * exec_list or any structure in which an \c exec_list is embedded.
+ *
  * To anyone familiar with "exec lists" on the Amiga, this structure should
  * be immediately recognizable.  See the following link for the original Amiga
  * operating system documentation on the subject.
@@ -69,7 +73,7 @@
 #endif
 #include <assert.h>
 
-#include "ralloc.h"
+#include "util/ralloc.h"
 
 struct exec_node {
    struct exec_node *next;
@@ -325,6 +329,8 @@ struct exec_list {
    const exec_node *get_tail() const;
    exec_node *get_tail();
 
+   unsigned length() const;
+
    void push_head(exec_node *n);
    void push_tail(exec_node *n);
    void push_degenerate_list_at_head(exec_node *n);
@@ -345,9 +351,15 @@ struct exec_list {
    void move_nodes_to(exec_list *target);
 
    /**
-    * Append all nodes from the source list to the target list
+    * Append all nodes from the source list to the end of the target list
     */
    void append_list(exec_list *source);
+
+   /**
+    * Prepend all nodes from the source list to the beginning of the target
+    * list
+    */
+   void prepend_list(exec_list *source);
 #endif
 };
 
@@ -399,6 +411,19 @@ exec_list_get_tail(struct exec_list *list)
    return !exec_list_is_empty(list) ? list->tail_pred : NULL;
 }
 
+static inline unsigned
+exec_list_length(const struct exec_list *list)
+{
+   unsigned size = 0;
+   struct exec_node *node;
+
+   for (node = list->head; node->next != NULL; node = node->next) {
+      size++;
+   }
+
+   return size;
+}
+
 static inline void
 exec_list_push_head(struct exec_list *list, struct exec_node *n)
 {
@@ -478,6 +503,13 @@ exec_list_append(struct exec_list *list, struct exec_list *source)
    exec_list_make_empty(source);
 }
 
+static inline void
+exec_list_prepend(struct exec_list *list, struct exec_list *source)
+{
+   exec_list_append(source, list);
+   exec_list_move_nodes_to(source, list);
+}
+
 static inline void
 exec_node_insert_list_before(struct exec_node *n, struct exec_list *before)
 {
@@ -493,6 +525,25 @@ exec_node_insert_list_before(struct exec_node *n, struct exec_list *before)
    exec_list_make_empty(before);
 }
 
+static inline void
+exec_list_validate(const struct exec_list *list)
+{
+   const struct exec_node *node;
+
+   assert(list->head->prev == (const struct exec_node *) &list->head);
+   assert(list->tail == NULL);
+   assert(list->tail_pred->next == (const struct exec_node *) &list->tail);
+
+   /* We could try to use one of the interators below for this but they all
+    * either require C++ or assume the exec_node is embedded in a structure
+    * which is not the case for this function.
+    */
+   for (node = list->head; node->next != NULL; node = node->next) {
+      assert(node->next->prev == node);
+      assert(node->prev->next == node);
+   }
+}
+
 #ifdef __cplusplus
 inline void exec_list::make_empty()
 {
@@ -524,6 +575,11 @@ inline exec_node *exec_list::get_tail()
    return exec_list_get_tail(this);
 }
 
+inline unsigned exec_list::length() const
+{
+   return exec_list_length(this);
+}
+
 inline void exec_list::push_head(exec_node *n)
 {
    exec_list_push_head(this, n);
@@ -554,6 +610,11 @@ inline void exec_list::append_list(exec_list *source)
    exec_list_append(this, source);
 }
 
+inline void exec_list::prepend_list(exec_list *source)
+{
+   exec_list_prepend(this, source);
+}
+
 inline void exec_node::insert_before(exec_list *before)
 {
    exec_node_insert_list_before(this, before);
@@ -565,9 +626,9 @@ inline void exec_node::insert_before(exec_list *before)
         !(__inst)->is_tail_sentinel();               \
         (__inst) = (__type *)(__inst)->next)
 
-#define foreach_in_list_reverse(__type, __inst, __list) \
-   for (__type *(__inst) = (__type *)(__list)->head;    \
-        !(__inst)->is_head_sentinel();                  \
+#define foreach_in_list_reverse(__type, __inst, __list)   \
+   for (__type *(__inst) = (__type *)(__list)->tail_pred; \
+        !(__inst)->is_head_sentinel();                    \
         (__inst) = (__type *)(__inst)->prev)
 
 /**
@@ -579,6 +640,12 @@ inline void exec_node::insert_before(exec_list *before)
         __next != NULL;                              \
         __node = __next, __next = (__type *)__next->next)
 
+#define foreach_in_list_reverse_safe(__type, __node, __list) \
+   for (__type *__node = (__type *)(__list)->tail_pred,      \
+               *__prev = (__type *)__node->prev;             \
+        __prev != NULL;                                      \
+        __node = __prev, __prev = (__type *)__prev->prev)
+
 #define foreach_in_list_use_after(__type, __inst, __list) \
    __type *(__inst);                                      \
    for ((__inst) = (__type *)(__list)->head;              \
@@ -606,13 +673,28 @@ inline void exec_node::insert_before(exec_list *before)
        (__node)->__field.next != NULL;                                 \
        (__node) = exec_node_data(__type, (__node)->__field.next, __field))
 
+#define foreach_list_typed_reverse(__type, __node, __field, __list)        \
+   for (__type * __node =                                                \
+           exec_node_data(__type, (__list)->tail_pred, __field);        \
+        (__node)->__field.prev != NULL;                                 \
+        (__node) = exec_node_data(__type, (__node)->__field.prev, __field))
+
 #define foreach_list_typed_safe(__type, __node, __field, __list)           \
    for (__type * __node =                                                  \
            exec_node_data(__type, (__list)->head, __field),                \
                * __next =                                                  \
            exec_node_data(__type, (__node)->__field.next, __field);        \
-        __next != NULL;                                                    \
+        (__node)->__field.next != NULL;                                    \
         __node = __next, __next =                                          \
            exec_node_data(__type, (__next)->__field.next, __field))
 
+#define foreach_list_typed_safe_reverse(__type, __node, __field, __list)   \
+   for (__type * __node =                                                  \
+           exec_node_data(__type, (__list)->tail_pred, __field),           \
+               * __prev =                                                  \
+           exec_node_data(__type, (__node)->__field.prev, __field);        \
+        (__node)->__field.prev != NULL;                                    \
+        __node = __prev, __prev =                                          \
+           exec_node_data(__type, (__prev)->__field.prev, __field))
+
 #endif /* LIST_CONTAINER_H */