summaryrefslogtreecommitdiff
path: root/dviware/catdvi/vlist.c
diff options
context:
space:
mode:
Diffstat (limited to 'dviware/catdvi/vlist.c')
-rw-r--r--dviware/catdvi/vlist.c231
1 files changed, 231 insertions, 0 deletions
diff --git a/dviware/catdvi/vlist.c b/dviware/catdvi/vlist.c
new file mode 100644
index 0000000000..c1d1b2effb
--- /dev/null
+++ b/dviware/catdvi/vlist.c
@@ -0,0 +1,231 @@
+/* catdvi - get text from DVI files
+ Copyright (C) 2002 Bjoern Brill <brill@fs.math.uni-frankfurt.de>
+
+ 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.
+*/
+
+#include <stddef.h>
+#include <stdlib.h>
+#include <assert.h>
+#include "vlist.h"
+#include "util.h"
+
+#ifndef NDEBUG
+
+/* try to catch accesses to freed list nodes */
+static const vlist_node_t dead_node = {NULL, NULL, NULL};
+#define free_node(p) {*(p) = dead_node; free(p);}
+
+#else
+
+#define free_node(p) free(p)
+
+#endif
+
+
+void vlist_init(vlist_t * this)
+{
+ this->rend_node.prev = NULL;
+ this->rend_node.next = vlist_end(this);
+ this->rend_node.data = NULL;
+
+ this->end_node.prev = vlist_rend(this);
+ this->end_node.next = NULL;
+ this->end_node.data = NULL;
+
+ this->size = 0;
+}
+
+void vlist_done(vlist_t * this)
+{
+ vlist_clear(this);
+ this->rend_node.next = NULL;
+ this->end_node.prev = NULL;
+ this->size = 0;
+}
+
+
+void vlist_push_front(vlist_t * this, void const * newdata)
+{
+ vlist_insert_before(this, vlist_begin(this), newdata);
+}
+
+void vlist_pop_front(vlist_t * this)
+{
+ assert(this->size > 0);
+ vlist_erase(this, vlist_begin(this));
+}
+
+void vlist_push_back(vlist_t * this, void const * newdata)
+{
+ vlist_insert_after(this, vlist_rbegin(this), newdata);
+}
+
+void vlist_pop_back(vlist_t * this)
+{
+ assert(this->size > 0);
+ vlist_erase(this, vlist_rbegin(this));
+}
+
+
+vitor_t vlist_insert_before(
+ vlist_t * this,
+ vitor_t where,
+ void const * newdata
+)
+{
+ vitor_t prev, newnode;
+
+ assert(where != vlist_rend(this));
+ prev = where->prev;
+
+ newnode = malloc(sizeof(vlist_node_t));
+ if(newnode == NULL) enomem();
+
+ newnode->prev = prev;
+ newnode->next = where;
+ newnode->data = (void *) newdata; /* de-const is intentional */
+
+ prev->next = newnode;
+ where->prev = newnode;
+
+ this->size += 1;
+ return newnode;
+}
+
+vitor_t vlist_insert_after(
+ vlist_t * this,
+ vitor_t where,
+ void const * newdata
+)
+{
+ vitor_t next, newnode;
+
+ assert(where != vlist_end(this));
+ next = where->next;
+
+ newnode = malloc(sizeof(vlist_node_t));
+ if(newnode == NULL) enomem();
+
+ newnode->prev = where;
+ newnode->next = next;
+ newnode->data = (void *) newdata; /* de-const is intentional */
+
+ where->next = newnode;
+ next->prev = newnode;
+
+ this->size += 1;
+ return newnode;
+}
+
+void vlist_erase(vlist_t * this, vitor_t what)
+{
+ vitor_t prev, next;
+
+ assert(what != vlist_rend(this));
+ assert(what != vlist_end(this));
+ prev = what->prev;
+ next = what->next;
+
+ prev->next = next;
+ next->prev = prev;
+
+ free_node(what);
+ this->size -= 1;
+}
+
+void vlist_clear(vlist_t * this)
+{
+ vitor_t p, q;
+
+ for(p = vlist_begin(this); p != vlist_end(this); p = q) {
+ q = p->next;
+ free_node(p);
+ }
+
+ this->rend_node.next = vlist_end(this);
+ this->end_node.prev = vlist_rend(this);
+
+ this->size = 0;
+}
+
+
+void vlist_swap_consecutive(vlist_t * this, vitor_t first, vitor_t second)
+{
+ vitor_t prev, next;
+
+ assert(first != vlist_rend(this));
+ assert(second != vlist_end(this));
+ assert(first->next == second);
+
+ prev = first->prev;
+ next = second->next;
+
+ prev->next = second;
+ second->next = first;
+ first->next = next;
+
+ next->prev = first;
+ first->prev = second;
+ second->prev = prev;
+}
+
+void vlist_move_before(vlist_t * this, vitor_t where, vitor_t what)
+{
+ vitor_t oldprev, oldnext, newprev;
+
+ assert(what != vlist_rend(this));
+ assert(what != vlist_end(this));
+ assert(where != vlist_rend(this));
+ assert(what != where);
+
+ /* unlink what */
+ oldprev = what->prev;
+ oldnext = what->next;
+ oldprev->next = oldnext;
+ oldnext->prev = oldprev;
+
+ /* and link in before where */
+ newprev = where->prev;
+ /* don't do this earlier or it will break if where->prev == what */
+ newprev->next = what;
+ what->next = where;
+ where->prev = what;
+ what->prev = newprev;
+}
+
+void vlist_move_after(vlist_t * this, vitor_t where, vitor_t what)
+{
+ vitor_t oldprev, oldnext, newnext;
+
+ assert(what != vlist_rend(this));
+ assert(what != vlist_end(this));
+ assert(where != vlist_end(this));
+ assert(what != where);
+
+ /* unlink what */
+ oldprev = what->prev;
+ oldnext = what->next;
+ oldprev->next = oldnext;
+ oldnext->prev = oldprev;
+
+ /* and link in after where */
+ newnext = where->next;
+ /* don't do this earlier or it will break if where->next == what */
+ where->next = what;
+ what->next = newnext;
+ newnext->prev = what;
+ what->prev = where;
+}