exploded out the source code
This commit is contained in:
parent
56761e0ab7
commit
085fdb6a95
172 changed files with 3039 additions and 194 deletions
2
.gitignore
vendored
2
.gitignore
vendored
|
|
@ -14,3 +14,5 @@ stats.ods
|
|||
bin/
|
||||
typescript
|
||||
.main.c.swp
|
||||
.build-cache/
|
||||
__pycache__
|
||||
|
|
|
|||
596
avl/avl.c
Normal file
596
avl/avl.c
Normal file
|
|
@ -0,0 +1,596 @@
|
|||
/*****************************************************************************
|
||||
|
||||
avl.c - Source code for the AVL-tree library.
|
||||
|
||||
Copyright (C) 1998 Michael H. Buselli <cosine@cosine.org>
|
||||
Copyright (C) 2000-2002 Wessel Dankers <wsl@nl.linux.org>
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2.1 of the License, or (at your option) any later version.
|
||||
|
||||
This library 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
|
||||
Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public
|
||||
License along with this library; if not, write to the Free Software
|
||||
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
|
||||
Augmented AVL-tree. Original by Michael H. Buselli <cosine@cosine.org>.
|
||||
|
||||
Modified by Wessel Dankers <wsl@nl.linux.org> to add a bunch of bloat to
|
||||
the sourcecode, change the interface and squash a few bugs.
|
||||
Mail him if you find new bugs.
|
||||
|
||||
*****************************************************************************/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <errno.h>
|
||||
|
||||
#include "avl.h"
|
||||
|
||||
#pragma GCC diagnostic push
|
||||
#pragma GCC diagnostic ignored "-Wconversion"
|
||||
|
||||
static void avl_rebalance(avl_tree_t *, avl_node_t *);
|
||||
|
||||
#ifdef AVL_COUNT
|
||||
#define NODE_COUNT(n) ((n) ? (n)->count : 0)
|
||||
#define L_COUNT(n) (NODE_COUNT((n)->left))
|
||||
#define R_COUNT(n) (NODE_COUNT((n)->right))
|
||||
#define CALC_COUNT(n) (L_COUNT(n) + R_COUNT(n) + 1)
|
||||
#endif
|
||||
|
||||
#ifdef AVL_DEPTH
|
||||
#define NODE_DEPTH(n) ((n) ? (n)->depth : 0)
|
||||
#define L_DEPTH(n) (NODE_DEPTH((n)->left))
|
||||
#define R_DEPTH(n) (NODE_DEPTH((n)->right))
|
||||
#define CALC_DEPTH(n) ((L_DEPTH(n)>R_DEPTH(n)?L_DEPTH(n):R_DEPTH(n)) + 1)
|
||||
#endif
|
||||
|
||||
#ifndef AVL_DEPTH
|
||||
/* Also known as ffs() (from BSD) */
|
||||
static int lg(unsigned int u) {
|
||||
int r = 1;
|
||||
if(!u) return 0;
|
||||
if(u & 0xffff0000) { u >>= 16; r += 16; }
|
||||
if(u & 0x0000ff00) { u >>= 8; r += 8; }
|
||||
if(u & 0x000000f0) { u >>= 4; r += 4; }
|
||||
if(u & 0x0000000c) { u >>= 2; r += 2; }
|
||||
if(u & 0x00000002) r++;
|
||||
return r;
|
||||
}
|
||||
#endif
|
||||
|
||||
static int avl_check_balance(avl_node_t *avlnode) {
|
||||
#ifdef AVL_DEPTH
|
||||
int d;
|
||||
d = R_DEPTH(avlnode) - L_DEPTH(avlnode);
|
||||
return d<-1?-1:d>1?1:0;
|
||||
#else
|
||||
/* int d;
|
||||
* d = lg(R_COUNT(avlnode)) - lg(L_COUNT(avlnode));
|
||||
* d = d<-1?-1:d>1?1:0;
|
||||
*/
|
||||
#ifdef AVL_COUNT
|
||||
int pl, r;
|
||||
|
||||
pl = lg(L_COUNT(avlnode));
|
||||
r = R_COUNT(avlnode);
|
||||
|
||||
if(r>>pl+1)
|
||||
return 1;
|
||||
if(pl<2 || r>>pl-2)
|
||||
return 0;
|
||||
return -1;
|
||||
#else
|
||||
#error No balancing possible.
|
||||
#endif
|
||||
#endif
|
||||
}
|
||||
|
||||
#ifdef AVL_COUNT
|
||||
unsigned int avl_count(const avl_tree_t *avltree) {
|
||||
return NODE_COUNT(avltree->top);
|
||||
}
|
||||
|
||||
avl_node_t *avl_at(const avl_tree_t *avltree, unsigned int index) {
|
||||
avl_node_t *avlnode;
|
||||
unsigned int c;
|
||||
|
||||
avlnode = avltree->top;
|
||||
|
||||
while(avlnode) {
|
||||
c = L_COUNT(avlnode);
|
||||
|
||||
if(index < c) {
|
||||
avlnode = avlnode->left;
|
||||
} else if(index > c) {
|
||||
avlnode = avlnode->right;
|
||||
index -= c+1;
|
||||
} else {
|
||||
return avlnode;
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
unsigned int avl_index(const avl_node_t *avlnode) {
|
||||
avl_node_t *next;
|
||||
unsigned int c;
|
||||
|
||||
c = L_COUNT(avlnode);
|
||||
|
||||
while((next = avlnode->parent)) {
|
||||
if(avlnode == next->right)
|
||||
c += L_COUNT(next) + 1;
|
||||
avlnode = next;
|
||||
}
|
||||
|
||||
return c;
|
||||
}
|
||||
#endif
|
||||
|
||||
int avl_search_closest(const avl_tree_t *avltree, const void *item, avl_node_t **avlnode) {
|
||||
avl_node_t *node;
|
||||
avl_compare_t cmp;
|
||||
int c;
|
||||
|
||||
if(!avlnode)
|
||||
avlnode = &node;
|
||||
|
||||
node = avltree->top;
|
||||
|
||||
if(!node)
|
||||
return *avlnode = NULL, 0;
|
||||
|
||||
cmp = avltree->cmp;
|
||||
|
||||
for(;;) {
|
||||
c = cmp(item, node->item);
|
||||
|
||||
if(c < 0) {
|
||||
if(node->left)
|
||||
node = node->left;
|
||||
else
|
||||
return *avlnode = node, -1;
|
||||
} else if(c > 0) {
|
||||
if(node->right)
|
||||
node = node->right;
|
||||
else
|
||||
return *avlnode = node, 1;
|
||||
} else {
|
||||
return *avlnode = node, 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* avl_search:
|
||||
* Return a pointer to a node with the given item in the tree.
|
||||
* If no such item is in the tree, then NULL is returned.
|
||||
*/
|
||||
avl_node_t *avl_search(const avl_tree_t *avltree, const void *item) {
|
||||
avl_node_t *node;
|
||||
return avl_search_closest(avltree, item, &node) ? NULL : node;
|
||||
}
|
||||
|
||||
avl_tree_t *avl_init_tree(avl_tree_t *rc, avl_compare_t cmp, avl_freeitem_t freeitem) {
|
||||
if(rc) {
|
||||
rc->head = NULL;
|
||||
rc->tail = NULL;
|
||||
rc->top = NULL;
|
||||
rc->cmp = cmp;
|
||||
rc->freeitem = freeitem;
|
||||
}
|
||||
return rc;
|
||||
}
|
||||
|
||||
avl_tree_t *avl_alloc_tree(avl_compare_t cmp, avl_freeitem_t freeitem) {
|
||||
return avl_init_tree(malloc(sizeof(avl_tree_t)), cmp, freeitem);
|
||||
}
|
||||
|
||||
void avl_clear_tree(avl_tree_t *avltree) {
|
||||
avltree->top = avltree->head = avltree->tail = NULL;
|
||||
}
|
||||
|
||||
void avl_free_nodes(avl_tree_t *avltree) {
|
||||
avl_node_t *node, *next;
|
||||
avl_freeitem_t freeitem;
|
||||
|
||||
freeitem = avltree->freeitem;
|
||||
|
||||
for(node = avltree->head; node; node = next) {
|
||||
next = node->next;
|
||||
if(freeitem)
|
||||
freeitem(node->item);
|
||||
free(node);
|
||||
}
|
||||
|
||||
avl_clear_tree(avltree);
|
||||
}
|
||||
|
||||
/*
|
||||
* avl_free_tree:
|
||||
* Free all memory used by this tree. If freeitem is not NULL, then
|
||||
* it is assumed to be a destructor for the items referenced in the avl_
|
||||
* tree, and they are deleted as well.
|
||||
*/
|
||||
void avl_free_tree(avl_tree_t *avltree) {
|
||||
avl_free_nodes(avltree);
|
||||
free(avltree);
|
||||
}
|
||||
|
||||
static void avl_clear_node(avl_node_t *newnode) {
|
||||
newnode->left = newnode->right = NULL;
|
||||
#ifdef AVL_COUNT
|
||||
newnode->count = 1;
|
||||
#endif
|
||||
#ifdef AVL_DEPTH
|
||||
newnode->depth = 1;
|
||||
#endif
|
||||
}
|
||||
|
||||
avl_node_t *avl_init_node(avl_node_t *newnode, void *item) {
|
||||
if(newnode) {
|
||||
/* avl_clear_node(newnode); */
|
||||
newnode->item = item;
|
||||
}
|
||||
return newnode;
|
||||
}
|
||||
|
||||
avl_node_t *avl_insert_top(avl_tree_t *avltree, avl_node_t *newnode) {
|
||||
avl_clear_node(newnode);
|
||||
newnode->prev = newnode->next = newnode->parent = NULL;
|
||||
avltree->head = avltree->tail = avltree->top = newnode;
|
||||
return newnode;
|
||||
}
|
||||
|
||||
avl_node_t *avl_insert_before(avl_tree_t *avltree, avl_node_t *node, avl_node_t *newnode) {
|
||||
if(!node)
|
||||
return avltree->tail
|
||||
? avl_insert_after(avltree, avltree->tail, newnode)
|
||||
: avl_insert_top(avltree, newnode);
|
||||
|
||||
if(node->left)
|
||||
return avl_insert_after(avltree, node->prev, newnode);
|
||||
|
||||
avl_clear_node(newnode);
|
||||
|
||||
newnode->next = node;
|
||||
newnode->parent = node;
|
||||
|
||||
newnode->prev = node->prev;
|
||||
if(node->prev)
|
||||
node->prev->next = newnode;
|
||||
else
|
||||
avltree->head = newnode;
|
||||
node->prev = newnode;
|
||||
|
||||
node->left = newnode;
|
||||
avl_rebalance(avltree, node);
|
||||
return newnode;
|
||||
}
|
||||
|
||||
avl_node_t *avl_insert_after(avl_tree_t *avltree, avl_node_t *node, avl_node_t *newnode) {
|
||||
if(!node)
|
||||
return avltree->head
|
||||
? avl_insert_before(avltree, avltree->head, newnode)
|
||||
: avl_insert_top(avltree, newnode);
|
||||
|
||||
if(node->right)
|
||||
return avl_insert_before(avltree, node->next, newnode);
|
||||
|
||||
avl_clear_node(newnode);
|
||||
|
||||
newnode->prev = node;
|
||||
newnode->parent = node;
|
||||
|
||||
newnode->next = node->next;
|
||||
if(node->next)
|
||||
node->next->prev = newnode;
|
||||
else
|
||||
avltree->tail = newnode;
|
||||
node->next = newnode;
|
||||
|
||||
node->right = newnode;
|
||||
avl_rebalance(avltree, node);
|
||||
return newnode;
|
||||
}
|
||||
|
||||
avl_node_t *avl_insert_node(avl_tree_t *avltree, avl_node_t *newnode) {
|
||||
avl_node_t *node;
|
||||
|
||||
if(!avltree->top)
|
||||
return avl_insert_top(avltree, newnode);
|
||||
|
||||
switch(avl_search_closest(avltree, newnode->item, &node)) {
|
||||
case -1:
|
||||
return avl_insert_before(avltree, node, newnode);
|
||||
case 1:
|
||||
return avl_insert_after(avltree, node, newnode);
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/*
|
||||
* avl_insert:
|
||||
* Create a new node and insert an item there.
|
||||
* Returns the new node on success or NULL if no memory could be allocated.
|
||||
*/
|
||||
avl_node_t *avl_insert(avl_tree_t *avltree, void *item) {
|
||||
avl_node_t *newnode;
|
||||
|
||||
newnode = avl_init_node(malloc(sizeof(avl_node_t)), item);
|
||||
if(newnode) {
|
||||
if(avl_insert_node(avltree, newnode))
|
||||
return newnode;
|
||||
free(newnode);
|
||||
errno = EEXIST;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/*
|
||||
* avl_unlink_node:
|
||||
* Removes the given node. Does not delete the item at that node.
|
||||
* The item of the node may be freed before calling avl_unlink_node.
|
||||
* (In other words, it is not referenced by this function.)
|
||||
*/
|
||||
void avl_unlink_node(avl_tree_t *avltree, avl_node_t *avlnode) {
|
||||
avl_node_t *parent;
|
||||
avl_node_t **superparent;
|
||||
avl_node_t *subst, *left, *right;
|
||||
avl_node_t *balnode;
|
||||
|
||||
if(avlnode->prev)
|
||||
avlnode->prev->next = avlnode->next;
|
||||
else
|
||||
avltree->head = avlnode->next;
|
||||
|
||||
if(avlnode->next)
|
||||
avlnode->next->prev = avlnode->prev;
|
||||
else
|
||||
avltree->tail = avlnode->prev;
|
||||
|
||||
parent = avlnode->parent;
|
||||
|
||||
superparent = parent
|
||||
? avlnode == parent->left ? &parent->left : &parent->right
|
||||
: &avltree->top;
|
||||
|
||||
left = avlnode->left;
|
||||
right = avlnode->right;
|
||||
if(!left) {
|
||||
*superparent = right;
|
||||
if(right)
|
||||
right->parent = parent;
|
||||
balnode = parent;
|
||||
} else if(!right) {
|
||||
*superparent = left;
|
||||
left->parent = parent;
|
||||
balnode = parent;
|
||||
} else {
|
||||
subst = avlnode->prev;
|
||||
if(subst == left) {
|
||||
balnode = subst;
|
||||
} else {
|
||||
balnode = subst->parent;
|
||||
balnode->right = subst->left;
|
||||
if(balnode->right)
|
||||
balnode->right->parent = balnode;
|
||||
subst->left = left;
|
||||
left->parent = subst;
|
||||
}
|
||||
subst->right = right;
|
||||
subst->parent = parent;
|
||||
right->parent = subst;
|
||||
*superparent = subst;
|
||||
}
|
||||
|
||||
avl_rebalance(avltree, balnode);
|
||||
}
|
||||
|
||||
void *avl_delete_node(avl_tree_t *avltree, avl_node_t *avlnode) {
|
||||
void *item = NULL;
|
||||
if(avlnode) {
|
||||
item = avlnode->item;
|
||||
avl_unlink_node(avltree, avlnode);
|
||||
if(avltree->freeitem)
|
||||
avltree->freeitem(item);
|
||||
free(avlnode);
|
||||
}
|
||||
return item;
|
||||
}
|
||||
|
||||
void *avl_delete(avl_tree_t *avltree, const void *item) {
|
||||
return avl_delete_node(avltree, avl_search(avltree, item));
|
||||
}
|
||||
|
||||
avl_node_t *avl_fixup_node(avl_tree_t *avltree, avl_node_t *newnode) {
|
||||
avl_node_t *oldnode = NULL, *node;
|
||||
|
||||
if(!avltree || !newnode)
|
||||
return NULL;
|
||||
|
||||
node = newnode->prev;
|
||||
if(node) {
|
||||
oldnode = node->next;
|
||||
node->next = newnode;
|
||||
} else {
|
||||
avltree->head = newnode;
|
||||
}
|
||||
|
||||
node = newnode->next;
|
||||
if(node) {
|
||||
oldnode = node->prev;
|
||||
node->prev = newnode;
|
||||
} else {
|
||||
avltree->tail = newnode;
|
||||
}
|
||||
|
||||
node = newnode->parent;
|
||||
if(node) {
|
||||
if(node->left == oldnode)
|
||||
node->left = newnode;
|
||||
else
|
||||
node->right = newnode;
|
||||
} else {
|
||||
oldnode = avltree->top;
|
||||
avltree->top = newnode;
|
||||
}
|
||||
|
||||
return oldnode;
|
||||
}
|
||||
|
||||
/*
|
||||
* avl_rebalance:
|
||||
* Rebalances the tree if one side becomes too heavy. This function
|
||||
* assumes that both subtrees are AVL-trees with consistant data. The
|
||||
* function has the additional side effect of recalculating the count of
|
||||
* the tree at this node. It should be noted that at the return of this
|
||||
* function, if a rebalance takes place, the top of this subtree is no
|
||||
* longer going to be the same node.
|
||||
*/
|
||||
void avl_rebalance(avl_tree_t *avltree, avl_node_t *avlnode) {
|
||||
avl_node_t *child;
|
||||
avl_node_t *gchild;
|
||||
avl_node_t *parent;
|
||||
avl_node_t **superparent;
|
||||
|
||||
parent = avlnode;
|
||||
|
||||
while(avlnode) {
|
||||
parent = avlnode->parent;
|
||||
|
||||
superparent = parent
|
||||
? avlnode == parent->left ? &parent->left : &parent->right
|
||||
: &avltree->top;
|
||||
|
||||
switch(avl_check_balance(avlnode)) {
|
||||
case -1:
|
||||
child = avlnode->left;
|
||||
#ifdef AVL_DEPTH
|
||||
if(L_DEPTH(child) >= R_DEPTH(child)) {
|
||||
#else
|
||||
#ifdef AVL_COUNT
|
||||
if(L_COUNT(child) >= R_COUNT(child)) {
|
||||
#else
|
||||
#error No balancing possible.
|
||||
#endif
|
||||
#endif
|
||||
avlnode->left = child->right;
|
||||
if(avlnode->left)
|
||||
avlnode->left->parent = avlnode;
|
||||
child->right = avlnode;
|
||||
avlnode->parent = child;
|
||||
*superparent = child;
|
||||
child->parent = parent;
|
||||
#ifdef AVL_COUNT
|
||||
avlnode->count = CALC_COUNT(avlnode);
|
||||
child->count = CALC_COUNT(child);
|
||||
#endif
|
||||
#ifdef AVL_DEPTH
|
||||
avlnode->depth = CALC_DEPTH(avlnode);
|
||||
child->depth = CALC_DEPTH(child);
|
||||
#endif
|
||||
} else {
|
||||
gchild = child->right;
|
||||
avlnode->left = gchild->right;
|
||||
if(avlnode->left)
|
||||
avlnode->left->parent = avlnode;
|
||||
child->right = gchild->left;
|
||||
if(child->right)
|
||||
child->right->parent = child;
|
||||
gchild->right = avlnode;
|
||||
if(gchild->right)
|
||||
gchild->right->parent = gchild;
|
||||
gchild->left = child;
|
||||
if(gchild->left)
|
||||
gchild->left->parent = gchild;
|
||||
*superparent = gchild;
|
||||
gchild->parent = parent;
|
||||
#ifdef AVL_COUNT
|
||||
avlnode->count = CALC_COUNT(avlnode);
|
||||
child->count = CALC_COUNT(child);
|
||||
gchild->count = CALC_COUNT(gchild);
|
||||
#endif
|
||||
#ifdef AVL_DEPTH
|
||||
avlnode->depth = CALC_DEPTH(avlnode);
|
||||
child->depth = CALC_DEPTH(child);
|
||||
gchild->depth = CALC_DEPTH(gchild);
|
||||
#endif
|
||||
}
|
||||
break;
|
||||
case 1:
|
||||
child = avlnode->right;
|
||||
#ifdef AVL_DEPTH
|
||||
if(R_DEPTH(child) >= L_DEPTH(child)) {
|
||||
#else
|
||||
#ifdef AVL_COUNT
|
||||
if(R_COUNT(child) >= L_COUNT(child)) {
|
||||
#else
|
||||
#error No balancing possible.
|
||||
#endif
|
||||
#endif
|
||||
avlnode->right = child->left;
|
||||
if(avlnode->right)
|
||||
avlnode->right->parent = avlnode;
|
||||
child->left = avlnode;
|
||||
avlnode->parent = child;
|
||||
*superparent = child;
|
||||
child->parent = parent;
|
||||
#ifdef AVL_COUNT
|
||||
avlnode->count = CALC_COUNT(avlnode);
|
||||
child->count = CALC_COUNT(child);
|
||||
#endif
|
||||
#ifdef AVL_DEPTH
|
||||
avlnode->depth = CALC_DEPTH(avlnode);
|
||||
child->depth = CALC_DEPTH(child);
|
||||
#endif
|
||||
} else {
|
||||
gchild = child->left;
|
||||
avlnode->right = gchild->left;
|
||||
if(avlnode->right)
|
||||
avlnode->right->parent = avlnode;
|
||||
child->left = gchild->right;
|
||||
if(child->left)
|
||||
child->left->parent = child;
|
||||
gchild->left = avlnode;
|
||||
if(gchild->left)
|
||||
gchild->left->parent = gchild;
|
||||
gchild->right = child;
|
||||
if(gchild->right)
|
||||
gchild->right->parent = gchild;
|
||||
*superparent = gchild;
|
||||
gchild->parent = parent;
|
||||
#ifdef AVL_COUNT
|
||||
avlnode->count = CALC_COUNT(avlnode);
|
||||
child->count = CALC_COUNT(child);
|
||||
gchild->count = CALC_COUNT(gchild);
|
||||
#endif
|
||||
#ifdef AVL_DEPTH
|
||||
avlnode->depth = CALC_DEPTH(avlnode);
|
||||
child->depth = CALC_DEPTH(child);
|
||||
gchild->depth = CALC_DEPTH(gchild);
|
||||
#endif
|
||||
}
|
||||
break;
|
||||
default:
|
||||
#ifdef AVL_COUNT
|
||||
avlnode->count = CALC_COUNT(avlnode);
|
||||
#endif
|
||||
#ifdef AVL_DEPTH
|
||||
avlnode->depth = CALC_DEPTH(avlnode);
|
||||
#endif
|
||||
}
|
||||
avlnode = parent;
|
||||
}
|
||||
}
|
||||
|
||||
#pragma GCC diagnostic pop
|
||||
186
avl/avl.h
Normal file
186
avl/avl.h
Normal file
|
|
@ -0,0 +1,186 @@
|
|||
/*****************************************************************************
|
||||
|
||||
avl.h - Source code for the AVL-tree library.
|
||||
|
||||
Copyright (C) 1998 Michael H. Buselli <cosine@cosine.org>
|
||||
Copyright (C) 2000-2002 Wessel Dankers <wsl@nl.linux.org>
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2.1 of the License, or (at your option) any later version.
|
||||
|
||||
This library 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
|
||||
Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public
|
||||
License along with this library; if not, write to the Free Software
|
||||
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
|
||||
Augmented AVL-tree. Original by Michael H. Buselli <cosine@cosine.org>.
|
||||
|
||||
Modified by Wessel Dankers <wsl@nl.linux.org> to add a bunch of bloat to
|
||||
the sourcecode, change the interface and squash a few bugs.
|
||||
Mail him if you find new bugs.
|
||||
|
||||
*****************************************************************************/
|
||||
|
||||
#ifndef _AVL_H
|
||||
#define _AVL_H
|
||||
|
||||
/* We need either depths, counts or both (the latter being the default) */
|
||||
#if !defined(AVL_DEPTH) && !defined(AVL_COUNT)
|
||||
#define AVL_DEPTH
|
||||
#define AVL_COUNT
|
||||
#endif
|
||||
|
||||
/* User supplied function to compare two items like strcmp() does.
|
||||
* For example: cmp(a,b) will return:
|
||||
* -1 if a < b
|
||||
* 0 if a = b
|
||||
* 1 if a > b
|
||||
*/
|
||||
typedef int (*avl_compare_t)(const void *, const void *);
|
||||
|
||||
/* User supplied function to delete an item when a node is free()d.
|
||||
* If NULL, the item is not free()d.
|
||||
*/
|
||||
typedef void (*avl_freeitem_t)(void *);
|
||||
|
||||
typedef struct avl_node_t {
|
||||
struct avl_node_t *next;
|
||||
struct avl_node_t *prev;
|
||||
struct avl_node_t *parent;
|
||||
struct avl_node_t *left;
|
||||
struct avl_node_t *right;
|
||||
void *item;
|
||||
#ifdef AVL_COUNT
|
||||
unsigned int count;
|
||||
#endif
|
||||
#ifdef AVL_DEPTH
|
||||
unsigned char depth;
|
||||
#endif
|
||||
} avl_node_t;
|
||||
|
||||
typedef struct avl_tree_t {
|
||||
avl_node_t *head;
|
||||
avl_node_t *tail;
|
||||
avl_node_t *top;
|
||||
avl_compare_t cmp;
|
||||
avl_freeitem_t freeitem;
|
||||
} avl_tree_t;
|
||||
|
||||
/* Initializes a new tree for elements that will be ordered using
|
||||
* the supplied strcmp()-like function.
|
||||
* Returns the value of avltree (even if it's NULL).
|
||||
* O(1) */
|
||||
extern avl_tree_t *avl_init_tree(avl_tree_t *avltree, avl_compare_t, avl_freeitem_t);
|
||||
|
||||
/* Allocates and initializes a new tree for elements that will be
|
||||
* ordered using the supplied strcmp()-like function.
|
||||
* Returns NULL if memory could not be allocated.
|
||||
* O(1) */
|
||||
extern avl_tree_t *avl_alloc_tree(avl_compare_t, avl_freeitem_t);
|
||||
|
||||
/* Frees the entire tree efficiently. Nodes will be free()d.
|
||||
* If the tree's freeitem is not NULL it will be invoked on every item.
|
||||
* O(n) */
|
||||
extern void avl_free_tree(avl_tree_t *);
|
||||
|
||||
/* Reinitializes the tree structure for reuse. Nothing is free()d.
|
||||
* Compare and freeitem functions are left alone.
|
||||
* O(1) */
|
||||
extern void avl_clear_tree(avl_tree_t *);
|
||||
|
||||
/* Free()s all nodes in the tree but leaves the tree itself.
|
||||
* If the tree's freeitem is not NULL it will be invoked on every item.
|
||||
* O(n) */
|
||||
extern void avl_free_nodes(avl_tree_t *);
|
||||
|
||||
/* Initializes memory for use as a node. Returns NULL if avlnode is NULL.
|
||||
* O(1) */
|
||||
extern avl_node_t *avl_init_node(avl_node_t *avlnode, void *item);
|
||||
|
||||
/* Insert an item into the tree and return the new node.
|
||||
* Returns NULL and sets errno if memory for the new node could not be
|
||||
* allocated or if the node is already in the tree (EEXIST).
|
||||
* O(lg n) */
|
||||
extern avl_node_t *avl_insert(avl_tree_t *, void *item);
|
||||
|
||||
/* Insert a node into the tree and return it.
|
||||
* Returns NULL if the node is already in the tree.
|
||||
* O(lg n) */
|
||||
extern avl_node_t *avl_insert_node(avl_tree_t *, avl_node_t *);
|
||||
|
||||
/* Insert a node in an empty tree. If avlnode is NULL, the tree will be
|
||||
* cleared and ready for re-use.
|
||||
* If the tree is not empty, the old nodes are left dangling.
|
||||
* O(1) */
|
||||
extern avl_node_t *avl_insert_top(avl_tree_t *, avl_node_t *avlnode);
|
||||
|
||||
/* Insert a node before another node. Returns the new node.
|
||||
* If old is NULL, the item is appended to the tree.
|
||||
* O(lg n) */
|
||||
extern avl_node_t *avl_insert_before(avl_tree_t *, avl_node_t *old, avl_node_t *new);
|
||||
|
||||
/* Insert a node after another node. Returns the new node.
|
||||
* If old is NULL, the item is prepended to the tree.
|
||||
* O(lg n) */
|
||||
extern avl_node_t *avl_insert_after(avl_tree_t *, avl_node_t *old, avl_node_t *new);
|
||||
|
||||
/* Deletes a node from the tree. Returns immediately if the node is NULL.
|
||||
* The item will not be free()d regardless of the tree's freeitem handler.
|
||||
* This function comes in handy if you need to update the search key.
|
||||
* O(lg n) */
|
||||
extern void avl_unlink_node(avl_tree_t *, avl_node_t *);
|
||||
|
||||
/* Deletes a node from the tree. Returns immediately if the node is NULL.
|
||||
* If the tree's freeitem is not NULL, it is invoked on the item.
|
||||
* If it is, returns the item.
|
||||
* O(lg n) */
|
||||
extern void *avl_delete_node(avl_tree_t *, avl_node_t *);
|
||||
|
||||
/* Searches for an item in the tree and deletes it if found.
|
||||
* If the tree's freeitem is not NULL, it is invoked on the item.
|
||||
* If it is, returns the item.
|
||||
* O(lg n) */
|
||||
extern void *avl_delete(avl_tree_t *, const void *item);
|
||||
|
||||
/* If exactly one node is moved in memory, this will fix the pointers
|
||||
* in the tree that refer to it. It must be an exact shallow copy.
|
||||
* Returns the pointer to the old position.
|
||||
* O(1) */
|
||||
extern avl_node_t *avl_fixup_node(avl_tree_t *, avl_node_t *new);
|
||||
|
||||
/* Searches for a node with the key closest (or equal) to the given item.
|
||||
* If avlnode is not NULL, *avlnode will be set to the node found or NULL
|
||||
* if the tree is empty. Return values:
|
||||
* -1 if the returned node is smaller
|
||||
* 0 if the returned node is equal or if the tree is empty
|
||||
* 1 if the returned node is greater
|
||||
* O(lg n) */
|
||||
extern int avl_search_closest(const avl_tree_t *, const void *item, avl_node_t **avlnode);
|
||||
|
||||
/* Searches for the item in the tree and returns a matching node if found
|
||||
* or NULL if not.
|
||||
* O(lg n) */
|
||||
extern avl_node_t *avl_search(const avl_tree_t *, const void *item);
|
||||
|
||||
#ifdef AVL_COUNT
|
||||
/* Returns the number of nodes in the tree.
|
||||
* O(1) */
|
||||
extern unsigned int avl_count(const avl_tree_t *);
|
||||
|
||||
/* Searches a node by its rank in the list. Counting starts at 0.
|
||||
* Returns NULL if the index exceeds the number of nodes in the tree.
|
||||
* O(lg n) */
|
||||
extern avl_node_t *avl_at(const avl_tree_t *, unsigned int);
|
||||
|
||||
/* Returns the rank of a node in the list. Counting starts at 0.
|
||||
* O(lg n) */
|
||||
extern unsigned int avl_index(const avl_node_t *);
|
||||
#endif
|
||||
|
||||
#endif
|
||||
0
calculate.c
Normal file
0
calculate.c
Normal file
0
calculate.h
Normal file
0
calculate.h
Normal file
11
cmdln/free.c
Normal file
11
cmdln/free.c
Normal file
|
|
@ -0,0 +1,11 @@
|
|||
|
||||
#include <debug.h>
|
||||
|
||||
#include "free.h"
|
||||
|
||||
void free_cmdln_flags(
|
||||
struct cmdln_flags* flags)
|
||||
{
|
||||
TODO;
|
||||
}
|
||||
|
||||
5
cmdln/free.h
Normal file
5
cmdln/free.h
Normal file
|
|
@ -0,0 +1,5 @@
|
|||
|
||||
struct cmdln_flags;
|
||||
|
||||
void free_cmdln_flags(
|
||||
struct cmdln_flags* flags);
|
||||
9
cmdln/print_usage.c
Normal file
9
cmdln/print_usage.c
Normal file
|
|
@ -0,0 +1,9 @@
|
|||
|
||||
#include <debug.h>
|
||||
|
||||
#include "print_usage.h"
|
||||
|
||||
void print_usage()
|
||||
{
|
||||
TODO;
|
||||
}
|
||||
3
cmdln/print_usage.h
Normal file
3
cmdln/print_usage.h
Normal file
|
|
@ -0,0 +1,3 @@
|
|||
|
||||
void print_usage(void);
|
||||
|
||||
254
cmdln/process.c
Normal file
254
cmdln/process.c
Normal file
|
|
@ -0,0 +1,254 @@
|
|||
|
||||
#include <debug.h>
|
||||
|
||||
#include <memory/smalloc.h>
|
||||
|
||||
#include "struct.h"
|
||||
#include "process.h"
|
||||
#include "print_usage.h"
|
||||
|
||||
static struct option long_options[] = {
|
||||
{"print-all-and-quit", no_argument, NULL, 't'},
|
||||
{"command", required_argument, NULL, 'c'},
|
||||
{"operators", required_argument, NULL, 'o'},
|
||||
{"print-stats", no_argument, NULL, 'm'},
|
||||
{"help", no_argument, NULL, 'h'},
|
||||
{0, 0, 0, 0}
|
||||
};
|
||||
|
||||
struct cmdln_flags* process_cmdln_flags(
|
||||
int argc,
|
||||
char* const* argv)
|
||||
{
|
||||
ENTER;
|
||||
|
||||
const char* command = NULL;
|
||||
|
||||
bool unset_operators = true;
|
||||
struct operators selected_operators = {};
|
||||
|
||||
bool unset_print_with_color = true;
|
||||
bool print_with_color;
|
||||
|
||||
bool print_all_and_quit = false;
|
||||
bool print_stats = false;
|
||||
|
||||
for (int opt, idx;
|
||||
(opt = getopt_long(argc, argv, "tc:o:mh", long_options, &idx)) != -1;)
|
||||
{
|
||||
switch (opt)
|
||||
{
|
||||
case 't':
|
||||
{
|
||||
print_all_and_quit = true;
|
||||
break;
|
||||
}
|
||||
|
||||
case 'c':
|
||||
{
|
||||
command = optarg;
|
||||
break;
|
||||
}
|
||||
|
||||
case 'o':
|
||||
{
|
||||
TODO;
|
||||
break;
|
||||
}
|
||||
|
||||
case 'm':
|
||||
{
|
||||
TODO;
|
||||
break;
|
||||
}
|
||||
|
||||
case 'h':
|
||||
{
|
||||
print_usage();
|
||||
exit(0);
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
{
|
||||
print_usage();
|
||||
exit(1);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (unset_operators)
|
||||
{
|
||||
selected_operators.not = true;
|
||||
selected_operators.or = true;
|
||||
selected_operators.and = true;
|
||||
}
|
||||
|
||||
if (unset_print_with_color)
|
||||
{
|
||||
if (isatty(1))
|
||||
{
|
||||
print_with_color = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
print_with_color = false;
|
||||
}
|
||||
}
|
||||
|
||||
struct cmdln_flags* flags = smalloc(sizeof(*flags));
|
||||
|
||||
flags->command = command;
|
||||
flags->selected_operators = selected_operators;
|
||||
flags->print_with_color = print_with_color;
|
||||
flags->print_stats = print_stats;
|
||||
flags->print_all_and_quit = print_all_and_quit;
|
||||
|
||||
EXIT;
|
||||
return flags;
|
||||
}
|
||||
|
||||
#if 0
|
||||
|
||||
static void parse_args(int argc, char* const* argv)
|
||||
{
|
||||
bool unset_operators = true;
|
||||
|
||||
print_with_color = isatty(1);
|
||||
|
||||
for (int opt; (opt = getopt(argc, argv, "tpyqmvc:eEo:C:B")) != -1; ) switch (opt)
|
||||
{
|
||||
case 't':
|
||||
print_truthtable = true;
|
||||
break;
|
||||
|
||||
case 'p':
|
||||
print_all_and_quit = true;
|
||||
break;
|
||||
|
||||
case 'y':
|
||||
assume_yes = true;
|
||||
break;
|
||||
|
||||
case 'q':
|
||||
quiet = true;
|
||||
break;
|
||||
|
||||
case 'm':
|
||||
print_stats = true;
|
||||
break;
|
||||
|
||||
case 'v':
|
||||
verbose = true;
|
||||
break;
|
||||
|
||||
case 'c':
|
||||
command = optarg;
|
||||
break;
|
||||
|
||||
case 'E':
|
||||
use_operators.ternary = true;
|
||||
// fallthrough
|
||||
|
||||
case 'e':
|
||||
{
|
||||
use_operators.not = true;
|
||||
use_operators.or = true;
|
||||
use_operators.and = true;
|
||||
|
||||
use_operators.orn = true;
|
||||
use_operators.nor = true;
|
||||
|
||||
use_operators.andn = true;
|
||||
use_operators.nand = true;
|
||||
|
||||
use_operators. xor = true;
|
||||
use_operators.nxor = true;
|
||||
|
||||
unset_operators = false;
|
||||
break;
|
||||
}
|
||||
|
||||
case 'o':
|
||||
{
|
||||
unset_operators = false;
|
||||
|
||||
for (char* moving; (moving = strtok_r(NULL, ",", &optarg)); )
|
||||
{
|
||||
if (!strcmp(moving, "not") || !strcmp(moving, "!"))
|
||||
use_operators.not = true;
|
||||
else if (!strcmp(moving, "or") || !strcmp(moving, "||"))
|
||||
use_operators.or = true;
|
||||
else if (!strcmp(moving, "orn") || !strcmp(moving, "|!"))
|
||||
use_operators.orn = true;
|
||||
else if (!strcmp(moving, "nor") || !strcmp(moving, "!|"))
|
||||
use_operators.nor = true;
|
||||
else if (!strcmp(moving, "and") || !strcmp(moving, "&&"))
|
||||
use_operators.and = true;
|
||||
else if (!strcmp(moving, "andn") || !strcmp(moving, "&!"))
|
||||
use_operators.andn = true;
|
||||
else if (!strcmp(moving, "nand") || !strcmp(moving, "!&"))
|
||||
use_operators.nand = true;
|
||||
else if (!strcmp(moving, "xor") || !strcmp(moving, "!="))
|
||||
use_operators.xor = true;
|
||||
else if (!strcmp(moving, "nxor") || !strcmp(moving, "=="))
|
||||
use_operators.nxor = true;
|
||||
else if (!strcmp(moving, "lt") || !strcmp(moving, "<"))
|
||||
use_operators.lt = true;
|
||||
else if (!strcmp(moving, "lte") || !strcmp(moving, "<="))
|
||||
use_operators.lte = true;
|
||||
else if (!strcmp(moving, "gt") || !strcmp(moving, ">"))
|
||||
use_operators.gt = true;
|
||||
else if (!strcmp(moving, "gte") || !strcmp(moving, ">="))
|
||||
use_operators.gte = true;
|
||||
else if (!strcmp(moving, "ternary") || !strcmp(moving, "?:"))
|
||||
use_operators.ternary = true;
|
||||
else
|
||||
{
|
||||
assert(!"TODO");
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case 'C':
|
||||
{
|
||||
if (!strcmp(optarg, "yes") || !strcmp(optarg, "on"))
|
||||
print_with_color = true;
|
||||
else if (!strcmp(optarg, "no") || !strcmp(optarg, "off"))
|
||||
print_with_color = false;
|
||||
else if (!strcmp(optarg, "auto"))
|
||||
print_with_color = isatty(1);
|
||||
else
|
||||
{
|
||||
assert(!"TODO");
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
case 'B':
|
||||
{
|
||||
force_rebuild = true;
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
{
|
||||
printf("Unknown option '%c'!" "\n", opt);
|
||||
exit(1);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (unset_operators)
|
||||
{
|
||||
use_operators.not = true;
|
||||
use_operators.or = true;
|
||||
use_operators.and = true;
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
4
cmdln/process.h
Normal file
4
cmdln/process.h
Normal file
|
|
@ -0,0 +1,4 @@
|
|||
|
||||
struct cmdln_flags* process_cmdln_flags(
|
||||
int argc,
|
||||
char* const* argv);
|
||||
54
cmdln/struct.h
Normal file
54
cmdln/struct.h
Normal file
|
|
@ -0,0 +1,54 @@
|
|||
|
||||
#include <stdbool.h>
|
||||
|
||||
#include <structs/operators.h>
|
||||
|
||||
struct cmdln_flags
|
||||
{
|
||||
const char* command;
|
||||
|
||||
struct operators selected_operators;
|
||||
|
||||
bool print_stats;
|
||||
bool print_all_and_quit;
|
||||
|
||||
bool print_with_color;
|
||||
|
||||
bool verbose;
|
||||
};
|
||||
|
||||
#if 0
|
||||
|
||||
bool print_all_and_quit = false;
|
||||
|
||||
const char* command = NULL;
|
||||
|
||||
struct {
|
||||
bool not;
|
||||
|
||||
bool or, orn, nor;
|
||||
|
||||
bool and, andn, nand;
|
||||
|
||||
bool xor, nxor;
|
||||
|
||||
bool lt, lte, gt, gte;
|
||||
|
||||
bool ternary;
|
||||
} use_operators;
|
||||
|
||||
bool print_truthtable = false;
|
||||
|
||||
bool assume_yes = false;
|
||||
|
||||
bool verbose = false;
|
||||
|
||||
bool print_with_color = false;
|
||||
|
||||
bool print_stats = false;
|
||||
|
||||
bool force_rebuild = false;
|
||||
|
||||
bool quiet = false;
|
||||
|
||||
#endif
|
||||
4
debug.c
Normal file
4
debug.c
Normal file
|
|
@ -0,0 +1,4 @@
|
|||
|
||||
#ifdef DEBUG_BUILD_TYPE
|
||||
int debug_depth;
|
||||
#endif
|
||||
46
debug.h
Normal file
46
debug.h
Normal file
|
|
@ -0,0 +1,46 @@
|
|||
|
||||
#ifdef DEBUG_BUILD_TYPE
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
#include <getopt.h>
|
||||
#include <assert.h>
|
||||
#include <stdbool.h>
|
||||
#include <inttypes.h>
|
||||
#include <limits.h>
|
||||
#include <string.h>
|
||||
|
||||
struct string;
|
||||
struct scope;
|
||||
struct expression;
|
||||
struct cmdln_flags;
|
||||
struct avl_tree_t;
|
||||
struct truthtable_set;
|
||||
|
||||
extern int debug_depth;
|
||||
|
||||
#include <typedefs/truthtable_t.h>
|
||||
|
||||
#include <memory/smalloc.h>
|
||||
|
||||
#include <string/inc.h>
|
||||
|
||||
#define ENTER \
|
||||
printf("%*s" "%s():" "\n", debug_depth++, "", __PRETTY_FUNCTION__);
|
||||
|
||||
#define TODO \
|
||||
assert(!"TODO");
|
||||
|
||||
#define CHECK \
|
||||
assert(!"CHECK");
|
||||
|
||||
#define EXIT \
|
||||
printf("%*s" "return; // from %s" "\n", debug_depth--, "", __PRETTY_FUNCTION__);
|
||||
|
||||
#endif
|
||||
|
||||
#ifdef RELEASE_BUILD_TYPE
|
||||
#define ENTER ;
|
||||
#define TODO ;
|
||||
#endif
|
||||
|
||||
2
defines/M.h
Normal file
2
defines/M.h
Normal file
|
|
@ -0,0 +1,2 @@
|
|||
|
||||
#define M (0b1111111111111111)
|
||||
1
defines/N.h
Normal file
1
defines/N.h
Normal file
|
|
@ -0,0 +1 @@
|
|||
#define N (65536)
|
||||
1
defines/W.h
Normal file
1
defines/W.h
Normal file
|
|
@ -0,0 +1 @@
|
|||
#define W 0b0101010101010101
|
||||
1
defines/X.h
Normal file
1
defines/X.h
Normal file
|
|
@ -0,0 +1 @@
|
|||
#define X 0b0011001100110011
|
||||
1
defines/Y.h
Normal file
1
defines/Y.h
Normal file
|
|
@ -0,0 +1 @@
|
|||
#define Y 0b0000111100001111
|
||||
1
defines/Z.h
Normal file
1
defines/Z.h
Normal file
|
|
@ -0,0 +1 @@
|
|||
#define Z 0b0000000011111111
|
||||
0
expression/and/evaluate.c
Normal file
0
expression/and/evaluate.c
Normal file
0
expression/and/evaluate.h
Normal file
0
expression/and/evaluate.h
Normal file
11
expression/and/free.c
Normal file
11
expression/and/free.c
Normal file
|
|
@ -0,0 +1,11 @@
|
|||
|
||||
#include <debug.h>
|
||||
|
||||
#include "free.h"
|
||||
|
||||
void free_and_expression(
|
||||
struct expression* super)
|
||||
{
|
||||
TODO;
|
||||
}
|
||||
|
||||
5
expression/and/free.h
Normal file
5
expression/and/free.h
Normal file
|
|
@ -0,0 +1,5 @@
|
|||
|
||||
struct expression;
|
||||
|
||||
void free_and_expression(
|
||||
struct expression* super);
|
||||
11
expression/and/inheritance.c
Normal file
11
expression/and/inheritance.c
Normal file
|
|
@ -0,0 +1,11 @@
|
|||
|
||||
#include "inheritance.h"
|
||||
#include "print.h"
|
||||
#include "free.h"
|
||||
|
||||
struct expression_inheritance and_expression_inheritance =
|
||||
{
|
||||
.print = and_expression_print,
|
||||
.free = free_and_expression,
|
||||
};
|
||||
|
||||
5
expression/and/inheritance.h
Normal file
5
expression/and/inheritance.h
Normal file
|
|
@ -0,0 +1,5 @@
|
|||
|
||||
#include "../inheritance.h"
|
||||
|
||||
extern struct expression_inheritance and_expression_inheritance;
|
||||
|
||||
27
expression/and/new.c
Normal file
27
expression/and/new.c
Normal file
|
|
@ -0,0 +1,27 @@
|
|||
|
||||
#include <debug.h>
|
||||
|
||||
#include "../new.h"
|
||||
#include "../inc.h"
|
||||
|
||||
#include "inheritance.h"
|
||||
#include "struct.h"
|
||||
#include "new.h"
|
||||
|
||||
struct expression* new_and_expression(
|
||||
int cost,
|
||||
struct expression* left,
|
||||
struct expression* right)
|
||||
{
|
||||
struct and_expression* this =
|
||||
(void*) new_expression(
|
||||
/* inheritance: */ &and_expression_inheritance,
|
||||
/* cost: */ cost,
|
||||
/* size: */ sizeof(*this));
|
||||
|
||||
this->left = inc_expression(left);
|
||||
this->right = inc_expression(right);
|
||||
|
||||
return (void*) this;
|
||||
}
|
||||
|
||||
5
expression/and/new.h
Normal file
5
expression/and/new.h
Normal file
|
|
@ -0,0 +1,5 @@
|
|||
|
||||
struct expression* new_and_expression(
|
||||
int cost,
|
||||
struct expression* left,
|
||||
struct expression* right);
|
||||
16
expression/and/print.c
Normal file
16
expression/and/print.c
Normal file
|
|
@ -0,0 +1,16 @@
|
|||
|
||||
#include <debug.h>
|
||||
|
||||
#include "../print.h"
|
||||
|
||||
#include "struct.h"
|
||||
#include "print.h"
|
||||
|
||||
void and_expression_print(
|
||||
struct expression* super)
|
||||
{
|
||||
struct and_expression* this = (void*) super;
|
||||
|
||||
printf("("), expression_print(this->left), printf(" && "), expression_print(this->right), printf(")");
|
||||
}
|
||||
|
||||
3
expression/and/print.h
Normal file
3
expression/and/print.h
Normal file
|
|
@ -0,0 +1,3 @@
|
|||
|
||||
void and_expression_print(
|
||||
struct expression* super);
|
||||
12
expression/and/struct.h
Normal file
12
expression/and/struct.h
Normal file
|
|
@ -0,0 +1,12 @@
|
|||
|
||||
#include "../struct.h"
|
||||
|
||||
struct and_expression
|
||||
{
|
||||
struct expression super;
|
||||
|
||||
struct expression* left;
|
||||
|
||||
struct expression* right;
|
||||
};
|
||||
|
||||
0
expression/evaluate.c
Normal file
0
expression/evaluate.c
Normal file
0
expression/evaluate.h
Normal file
0
expression/evaluate.h
Normal file
25
expression/free.c
Normal file
25
expression/free.c
Normal file
|
|
@ -0,0 +1,25 @@
|
|||
|
||||
#include <debug.h>
|
||||
|
||||
#include "inheritance.h"
|
||||
#include "struct.h"
|
||||
#include "free.h"
|
||||
|
||||
void free_expression(
|
||||
struct expression* this)
|
||||
{
|
||||
if (this)
|
||||
{
|
||||
if (!--this->refcount)
|
||||
{
|
||||
assert(this);
|
||||
|
||||
assert(this->inheritance);
|
||||
|
||||
assert(this->inheritance->free);
|
||||
|
||||
free(this);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
3
expression/free.h
Normal file
3
expression/free.h
Normal file
|
|
@ -0,0 +1,3 @@
|
|||
|
||||
void free_expression(
|
||||
struct expression* this);
|
||||
17
expression/inc.c
Normal file
17
expression/inc.c
Normal file
|
|
@ -0,0 +1,17 @@
|
|||
|
||||
#include <debug.h>
|
||||
|
||||
#include "struct.h"
|
||||
#include "inc.h"
|
||||
|
||||
struct expression* inc_expression(
|
||||
struct expression* this)
|
||||
{
|
||||
if (this)
|
||||
{
|
||||
this->refcount++;
|
||||
}
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
3
expression/inc.h
Normal file
3
expression/inc.h
Normal file
|
|
@ -0,0 +1,3 @@
|
|||
|
||||
struct expression* inc_expression(
|
||||
struct expression* this);
|
||||
12
expression/inheritance.h
Normal file
12
expression/inheritance.h
Normal file
|
|
@ -0,0 +1,12 @@
|
|||
|
||||
struct expression;
|
||||
|
||||
struct expression_inheritance
|
||||
{
|
||||
void (*print)(
|
||||
struct expression*);
|
||||
|
||||
void (*free)(
|
||||
struct expression*);
|
||||
};
|
||||
|
||||
0
expression/literal/evaluate.c
Normal file
0
expression/literal/evaluate.c
Normal file
0
expression/literal/evaluate.h
Normal file
0
expression/literal/evaluate.h
Normal file
11
expression/literal/free.c
Normal file
11
expression/literal/free.c
Normal file
|
|
@ -0,0 +1,11 @@
|
|||
|
||||
#include <debug.h>
|
||||
|
||||
#include "free.h"
|
||||
|
||||
void free_literal_expression(
|
||||
struct expression* super)
|
||||
{
|
||||
TODO;
|
||||
}
|
||||
|
||||
3
expression/literal/free.h
Normal file
3
expression/literal/free.h
Normal file
|
|
@ -0,0 +1,3 @@
|
|||
|
||||
void free_literal_expression(
|
||||
struct expression* super);
|
||||
11
expression/literal/inheritance.c
Normal file
11
expression/literal/inheritance.c
Normal file
|
|
@ -0,0 +1,11 @@
|
|||
|
||||
#include "inheritance.h"
|
||||
#include "print.h"
|
||||
#include "free.h"
|
||||
|
||||
struct expression_inheritance literal_expression_inheritance =
|
||||
{
|
||||
.print = literal_expression_print,
|
||||
.free = free_literal_expression,
|
||||
};
|
||||
|
||||
5
expression/literal/inheritance.h
Normal file
5
expression/literal/inheritance.h
Normal file
|
|
@ -0,0 +1,5 @@
|
|||
|
||||
#include "../inheritance.h"
|
||||
|
||||
extern struct expression_inheritance literal_expression_inheritance;
|
||||
|
||||
26
expression/literal/new.c
Normal file
26
expression/literal/new.c
Normal file
|
|
@ -0,0 +1,26 @@
|
|||
|
||||
#include <debug.h>
|
||||
|
||||
#include "../new.h"
|
||||
|
||||
#include "inheritance.h"
|
||||
#include "struct.h"
|
||||
#include "new.h"
|
||||
|
||||
struct expression* new_literal_expression(
|
||||
int cost, bool value)
|
||||
{
|
||||
ENTER;
|
||||
|
||||
struct literal_expression* this =
|
||||
(void*) new_expression(
|
||||
/* inheritance: */ &literal_expression_inheritance,
|
||||
/* cost: */ cost,
|
||||
/* size: */ sizeof(*this));
|
||||
|
||||
this->value = value;
|
||||
|
||||
EXIT;
|
||||
return (void*) this;
|
||||
}
|
||||
|
||||
4
expression/literal/new.h
Normal file
4
expression/literal/new.h
Normal file
|
|
@ -0,0 +1,4 @@
|
|||
|
||||
struct expression* new_literal_expression(
|
||||
int cost,
|
||||
bool is_one);
|
||||
21
expression/literal/print.c
Normal file
21
expression/literal/print.c
Normal file
|
|
@ -0,0 +1,21 @@
|
|||
|
||||
#include <debug.h>
|
||||
|
||||
#include "struct.h"
|
||||
#include "print.h"
|
||||
|
||||
void literal_expression_print(
|
||||
struct expression* super)
|
||||
{
|
||||
struct literal_expression* this = (void*) super;
|
||||
|
||||
if (this->value)
|
||||
{
|
||||
printf("1");
|
||||
}
|
||||
else
|
||||
{
|
||||
printf("0");
|
||||
}
|
||||
}
|
||||
|
||||
3
expression/literal/print.h
Normal file
3
expression/literal/print.h
Normal file
|
|
@ -0,0 +1,3 @@
|
|||
|
||||
void literal_expression_print(
|
||||
struct expression* super);
|
||||
10
expression/literal/struct.h
Normal file
10
expression/literal/struct.h
Normal file
|
|
@ -0,0 +1,10 @@
|
|||
|
||||
#include "../struct.h"
|
||||
|
||||
struct literal_expression
|
||||
{
|
||||
struct expression super;
|
||||
|
||||
bool value;
|
||||
};
|
||||
|
||||
22
expression/new.c
Normal file
22
expression/new.c
Normal file
|
|
@ -0,0 +1,22 @@
|
|||
|
||||
#include <debug.h>
|
||||
|
||||
#include "struct.h"
|
||||
#include "new.h"
|
||||
|
||||
struct expression* new_expression(
|
||||
const struct expression_inheritance* inheritance,
|
||||
int cost,
|
||||
size_t size)
|
||||
{
|
||||
struct expression* this = smalloc(size);
|
||||
|
||||
this->inheritance = inheritance;
|
||||
|
||||
this->cost = cost;
|
||||
|
||||
this->refcount = 1;
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
7
expression/new.h
Normal file
7
expression/new.h
Normal file
|
|
@ -0,0 +1,7 @@
|
|||
|
||||
struct expression_inheritance;
|
||||
|
||||
struct expression* new_expression(
|
||||
const struct expression_inheritance* inheritance,
|
||||
int cost,
|
||||
size_t size);
|
||||
0
expression/not/evaluate.c
Normal file
0
expression/not/evaluate.c
Normal file
0
expression/not/evaluate.h
Normal file
0
expression/not/evaluate.h
Normal file
11
expression/not/free.c
Normal file
11
expression/not/free.c
Normal file
|
|
@ -0,0 +1,11 @@
|
|||
|
||||
#include <debug.h>
|
||||
|
||||
#include "free.h"
|
||||
|
||||
void free_not_expression(
|
||||
struct expression* super)
|
||||
{
|
||||
TODO;
|
||||
}
|
||||
|
||||
5
expression/not/free.h
Normal file
5
expression/not/free.h
Normal file
|
|
@ -0,0 +1,5 @@
|
|||
|
||||
struct expression;
|
||||
|
||||
void free_not_expression(
|
||||
struct expression* super);
|
||||
11
expression/not/inheritance.c
Normal file
11
expression/not/inheritance.c
Normal file
|
|
@ -0,0 +1,11 @@
|
|||
|
||||
#include "inheritance.h"
|
||||
#include "print.h"
|
||||
#include "free.h"
|
||||
|
||||
struct expression_inheritance not_expression_inheritance =
|
||||
{
|
||||
.print = not_expression_print,
|
||||
.free = free_not_expression,
|
||||
};
|
||||
|
||||
5
expression/not/inheritance.h
Normal file
5
expression/not/inheritance.h
Normal file
|
|
@ -0,0 +1,5 @@
|
|||
|
||||
#include "../inheritance.h"
|
||||
|
||||
extern struct expression_inheritance not_expression_inheritance;
|
||||
|
||||
25
expression/not/new.c
Normal file
25
expression/not/new.c
Normal file
|
|
@ -0,0 +1,25 @@
|
|||
|
||||
#include <debug.h>
|
||||
|
||||
#include "../new.h"
|
||||
#include "../inc.h"
|
||||
|
||||
#include "inheritance.h"
|
||||
#include "struct.h"
|
||||
#include "new.h"
|
||||
|
||||
struct expression* new_not_expression(
|
||||
int cost,
|
||||
struct expression* inner)
|
||||
{
|
||||
struct not_expression* this =
|
||||
(void*) new_expression(
|
||||
/* inheritance: */ ¬_expression_inheritance,
|
||||
/* cost: */ cost,
|
||||
/* size: */ sizeof(*this));
|
||||
|
||||
this->inner = inc_expression(inner);
|
||||
|
||||
return (void*) this;
|
||||
}
|
||||
|
||||
4
expression/not/new.h
Normal file
4
expression/not/new.h
Normal file
|
|
@ -0,0 +1,4 @@
|
|||
|
||||
struct expression* new_not_expression(
|
||||
int cost,
|
||||
struct expression* subexpression);
|
||||
16
expression/not/print.c
Normal file
16
expression/not/print.c
Normal file
|
|
@ -0,0 +1,16 @@
|
|||
|
||||
#include <debug.h>
|
||||
|
||||
#include "../print.h"
|
||||
|
||||
#include "struct.h"
|
||||
#include "print.h"
|
||||
|
||||
void not_expression_print(
|
||||
struct expression* super)
|
||||
{
|
||||
struct not_expression* this = (void*) super;
|
||||
|
||||
printf("(!"), expression_print(this->inner), printf(")");
|
||||
}
|
||||
|
||||
3
expression/not/print.h
Normal file
3
expression/not/print.h
Normal file
|
|
@ -0,0 +1,3 @@
|
|||
|
||||
void not_expression_print(
|
||||
struct expression* super);
|
||||
10
expression/not/struct.h
Normal file
10
expression/not/struct.h
Normal file
|
|
@ -0,0 +1,10 @@
|
|||
|
||||
#include "../struct.h"
|
||||
|
||||
struct not_expression
|
||||
{
|
||||
struct expression super;
|
||||
|
||||
struct expression* inner;
|
||||
};
|
||||
|
||||
0
expression/or/evaluate.c
Normal file
0
expression/or/evaluate.c
Normal file
0
expression/or/evaluate.h
Normal file
0
expression/or/evaluate.h
Normal file
11
expression/or/free.c
Normal file
11
expression/or/free.c
Normal file
|
|
@ -0,0 +1,11 @@
|
|||
|
||||
#include <debug.h>
|
||||
|
||||
#include "free.h"
|
||||
|
||||
void free_or_expression(
|
||||
struct expression* super)
|
||||
{
|
||||
TODO;
|
||||
}
|
||||
|
||||
5
expression/or/free.h
Normal file
5
expression/or/free.h
Normal file
|
|
@ -0,0 +1,5 @@
|
|||
|
||||
struct expression;
|
||||
|
||||
void free_or_expression(
|
||||
struct expression* super);
|
||||
11
expression/or/inheritance.c
Normal file
11
expression/or/inheritance.c
Normal file
|
|
@ -0,0 +1,11 @@
|
|||
|
||||
#include "inheritance.h"
|
||||
#include "print.h"
|
||||
#include "free.h"
|
||||
|
||||
struct expression_inheritance or_expression_inheritance =
|
||||
{
|
||||
.print = or_expression_print,
|
||||
.free = free_or_expression,
|
||||
};
|
||||
|
||||
5
expression/or/inheritance.h
Normal file
5
expression/or/inheritance.h
Normal file
|
|
@ -0,0 +1,5 @@
|
|||
|
||||
#include "../inheritance.h"
|
||||
|
||||
extern struct expression_inheritance or_expression_inheritance;
|
||||
|
||||
27
expression/or/new.c
Normal file
27
expression/or/new.c
Normal file
|
|
@ -0,0 +1,27 @@
|
|||
|
||||
#include <debug.h>
|
||||
|
||||
#include "../new.h"
|
||||
#include "../inc.h"
|
||||
|
||||
#include "inheritance.h"
|
||||
#include "struct.h"
|
||||
#include "new.h"
|
||||
|
||||
struct expression* new_or_expression(
|
||||
int cost,
|
||||
struct expression* left,
|
||||
struct expression* right)
|
||||
{
|
||||
struct or_expression* this =
|
||||
(void*) new_expression(
|
||||
/* inheritance: */ &or_expression_inheritance,
|
||||
/* cost: */ cost,
|
||||
/* size: */ sizeof(*this));
|
||||
|
||||
this->left = inc_expression(left);
|
||||
this->right = inc_expression(right);
|
||||
|
||||
return (void*) this;
|
||||
}
|
||||
|
||||
5
expression/or/new.h
Normal file
5
expression/or/new.h
Normal file
|
|
@ -0,0 +1,5 @@
|
|||
|
||||
struct expression* new_or_expression(
|
||||
int cost,
|
||||
struct expression* left,
|
||||
struct expression* right);
|
||||
16
expression/or/print.c
Normal file
16
expression/or/print.c
Normal file
|
|
@ -0,0 +1,16 @@
|
|||
|
||||
#include <debug.h>
|
||||
|
||||
#include "../print.h"
|
||||
|
||||
#include "struct.h"
|
||||
#include "print.h"
|
||||
|
||||
void or_expression_print(
|
||||
struct expression* super)
|
||||
{
|
||||
struct or_expression* this = (void*) super;
|
||||
|
||||
printf("("), expression_print(this->left), printf(" || "), expression_print(this->right), printf(")");
|
||||
}
|
||||
|
||||
3
expression/or/print.h
Normal file
3
expression/or/print.h
Normal file
|
|
@ -0,0 +1,3 @@
|
|||
|
||||
void or_expression_print(
|
||||
struct expression* super);
|
||||
12
expression/or/struct.h
Normal file
12
expression/or/struct.h
Normal file
|
|
@ -0,0 +1,12 @@
|
|||
|
||||
#include "../struct.h"
|
||||
|
||||
struct or_expression
|
||||
{
|
||||
struct expression super;
|
||||
|
||||
struct expression* left;
|
||||
|
||||
struct expression* right;
|
||||
};
|
||||
|
||||
17
expression/print.c
Normal file
17
expression/print.c
Normal file
|
|
@ -0,0 +1,17 @@
|
|||
|
||||
#include <debug.h>
|
||||
|
||||
#include "inheritance.h"
|
||||
#include "struct.h"
|
||||
#include "print.h"
|
||||
|
||||
void expression_print(
|
||||
struct expression* this)
|
||||
{
|
||||
assert(this);
|
||||
assert(this->inheritance);
|
||||
assert(this->inheritance->print);
|
||||
|
||||
(this->inheritance->print)(this);
|
||||
}
|
||||
|
||||
5
expression/print.h
Normal file
5
expression/print.h
Normal file
|
|
@ -0,0 +1,5 @@
|
|||
|
||||
struct expression;
|
||||
|
||||
void expression_print(
|
||||
struct expression* this);
|
||||
12
expression/struct.h
Normal file
12
expression/struct.h
Normal file
|
|
@ -0,0 +1,12 @@
|
|||
|
||||
struct expression_inheritance;
|
||||
|
||||
struct expression
|
||||
{
|
||||
const struct expression_inheritance* inheritance;
|
||||
|
||||
int cost;
|
||||
|
||||
unsigned refcount;
|
||||
};
|
||||
|
||||
0
expression/unreachable/evaluate.c
Normal file
0
expression/unreachable/evaluate.c
Normal file
0
expression/unreachable/evaluate.h
Normal file
0
expression/unreachable/evaluate.h
Normal file
11
expression/unreachable/free.c
Normal file
11
expression/unreachable/free.c
Normal file
|
|
@ -0,0 +1,11 @@
|
|||
|
||||
#include <debug.h>
|
||||
|
||||
#include "free.h"
|
||||
|
||||
void free_unreachable_expression(
|
||||
struct expression* super)
|
||||
{
|
||||
TODO;
|
||||
}
|
||||
|
||||
3
expression/unreachable/free.h
Normal file
3
expression/unreachable/free.h
Normal file
|
|
@ -0,0 +1,3 @@
|
|||
|
||||
void free_unreachable_expression(
|
||||
struct expression* super);
|
||||
11
expression/unreachable/inheritance.c
Normal file
11
expression/unreachable/inheritance.c
Normal file
|
|
@ -0,0 +1,11 @@
|
|||
|
||||
#include "inheritance.h"
|
||||
#include "print.h"
|
||||
#include "free.h"
|
||||
|
||||
struct expression_inheritance unreachable_expression_inheritance =
|
||||
{
|
||||
.print = unreachable_expression_print,
|
||||
.free = free_unreachable_expression,
|
||||
};
|
||||
|
||||
5
expression/unreachable/inheritance.h
Normal file
5
expression/unreachable/inheritance.h
Normal file
|
|
@ -0,0 +1,5 @@
|
|||
|
||||
#include "../inheritance.h"
|
||||
|
||||
extern struct expression_inheritance unreachable_expression_inheritance;
|
||||
|
||||
23
expression/unreachable/new.c
Normal file
23
expression/unreachable/new.c
Normal file
|
|
@ -0,0 +1,23 @@
|
|||
|
||||
#include <debug.h>
|
||||
|
||||
#include "../new.h"
|
||||
|
||||
#include "inheritance.h"
|
||||
#include "struct.h"
|
||||
#include "new.h"
|
||||
|
||||
struct expression* new_unreachable_expression(void)
|
||||
{
|
||||
ENTER;
|
||||
|
||||
struct unreachable_expression* this =
|
||||
(void*) new_expression(
|
||||
/* inheritance: */ &unreachable_expression_inheritance,
|
||||
/* cost: */ INT_MAX,
|
||||
/* size: */ sizeof(*this));
|
||||
|
||||
EXIT;
|
||||
return (void*) this;
|
||||
}
|
||||
|
||||
2
expression/unreachable/new.h
Normal file
2
expression/unreachable/new.h
Normal file
|
|
@ -0,0 +1,2 @@
|
|||
|
||||
struct expression* new_unreachable_expression(void);
|
||||
11
expression/unreachable/print.c
Normal file
11
expression/unreachable/print.c
Normal file
|
|
@ -0,0 +1,11 @@
|
|||
|
||||
#include <debug.h>
|
||||
|
||||
#include "print.h"
|
||||
|
||||
void unreachable_expression_print(
|
||||
struct expression* super)
|
||||
{
|
||||
TODO;
|
||||
}
|
||||
|
||||
3
expression/unreachable/print.h
Normal file
3
expression/unreachable/print.h
Normal file
|
|
@ -0,0 +1,3 @@
|
|||
|
||||
void unreachable_expression_print(
|
||||
struct expression* super);
|
||||
8
expression/unreachable/struct.h
Normal file
8
expression/unreachable/struct.h
Normal file
|
|
@ -0,0 +1,8 @@
|
|||
|
||||
#include "../struct.h"
|
||||
|
||||
struct unreachable_expression
|
||||
{
|
||||
struct expression super;
|
||||
};
|
||||
|
||||
0
expression/variable/evaluate.c
Normal file
0
expression/variable/evaluate.c
Normal file
0
expression/variable/evaluate.h
Normal file
0
expression/variable/evaluate.h
Normal file
11
expression/variable/free.c
Normal file
11
expression/variable/free.c
Normal file
|
|
@ -0,0 +1,11 @@
|
|||
|
||||
#include <debug.h>
|
||||
|
||||
#include "free.h"
|
||||
|
||||
void free_variable_expression(
|
||||
struct expression* super)
|
||||
{
|
||||
TODO;
|
||||
}
|
||||
|
||||
3
expression/variable/free.h
Normal file
3
expression/variable/free.h
Normal file
|
|
@ -0,0 +1,3 @@
|
|||
|
||||
void free_variable_expression(
|
||||
struct expression* super);
|
||||
11
expression/variable/inheritance.c
Normal file
11
expression/variable/inheritance.c
Normal file
|
|
@ -0,0 +1,11 @@
|
|||
|
||||
#include "inheritance.h"
|
||||
#include "print.h"
|
||||
#include "free.h"
|
||||
|
||||
struct expression_inheritance variable_expression_inheritance =
|
||||
{
|
||||
.print = variable_expression_print,
|
||||
.free = free_variable_expression,
|
||||
};
|
||||
|
||||
5
expression/variable/inheritance.h
Normal file
5
expression/variable/inheritance.h
Normal file
|
|
@ -0,0 +1,5 @@
|
|||
|
||||
#include "../inheritance.h"
|
||||
|
||||
extern struct expression_inheritance variable_expression_inheritance;
|
||||
|
||||
27
expression/variable/new.c
Normal file
27
expression/variable/new.c
Normal file
|
|
@ -0,0 +1,27 @@
|
|||
|
||||
#include <debug.h>
|
||||
|
||||
#include "../new.h"
|
||||
|
||||
#include "inheritance.h"
|
||||
#include "struct.h"
|
||||
#include "new.h"
|
||||
|
||||
struct expression* new_variable_expression(
|
||||
int cost,
|
||||
struct string* name)
|
||||
{
|
||||
ENTER;
|
||||
|
||||
struct variable_expression* this =
|
||||
(void*) new_expression(
|
||||
/* inheritance: */ &variable_expression_inheritance,
|
||||
/* cost: */ cost,
|
||||
/* size: */ sizeof(*this));
|
||||
|
||||
this->name = inc_string(name);
|
||||
|
||||
EXIT;
|
||||
return (void*) this;
|
||||
}
|
||||
|
||||
4
expression/variable/new.h
Normal file
4
expression/variable/new.h
Normal file
|
|
@ -0,0 +1,4 @@
|
|||
|
||||
struct expression* new_variable_expression(
|
||||
int cost,
|
||||
struct string* name);
|
||||
16
expression/variable/print.c
Normal file
16
expression/variable/print.c
Normal file
|
|
@ -0,0 +1,16 @@
|
|||
|
||||
#include <debug.h>
|
||||
|
||||
#include <string/print.h>
|
||||
|
||||
#include "struct.h"
|
||||
#include "print.h"
|
||||
|
||||
void variable_expression_print(
|
||||
struct expression* super)
|
||||
{
|
||||
struct variable_expression* this = (void*) super;
|
||||
|
||||
string_print(this->name);
|
||||
}
|
||||
|
||||
3
expression/variable/print.h
Normal file
3
expression/variable/print.h
Normal file
|
|
@ -0,0 +1,3 @@
|
|||
|
||||
void variable_expression_print(
|
||||
struct expression* super);
|
||||
10
expression/variable/struct.h
Normal file
10
expression/variable/struct.h
Normal file
|
|
@ -0,0 +1,10 @@
|
|||
|
||||
#include "../struct.h"
|
||||
|
||||
struct variable_expression
|
||||
{
|
||||
struct expression super;
|
||||
|
||||
struct string* name;
|
||||
};
|
||||
|
||||
|
|
@ -25,10 +25,13 @@
|
|||
pkgs.mkShell {
|
||||
buildInputs = with pkgs; [
|
||||
gcc
|
||||
gnumake
|
||||
readline.dev
|
||||
python3
|
||||
];
|
||||
|
||||
shellHook = ''
|
||||
export PATH="$PWD:$PATH"
|
||||
'';
|
||||
};
|
||||
packages.default = pkgs.stdenv.mkDerivation rec {
|
||||
pname = "4-variable-simplifier";
|
||||
|
|
|
|||
233
main.c
233
main.c
|
|
@ -1,4 +1,18 @@
|
|||
|
||||
#include <assert.h>
|
||||
#include <debug.h>
|
||||
|
||||
#include <cmdln/struct.h>
|
||||
#include <cmdln/process.h>
|
||||
#include <cmdln/free.h>
|
||||
|
||||
#include <scope/new.h>
|
||||
#include <scope/free.h>
|
||||
|
||||
#include <simplifications/new.h>
|
||||
#include <simplifications/free.h>
|
||||
|
||||
#if 0
|
||||
#include <math.h>
|
||||
#include <string.h>
|
||||
#include <stdint.h>
|
||||
|
|
@ -14,8 +28,6 @@
|
|||
#include <readline/readline.h>
|
||||
#include <readline/history.h>
|
||||
|
||||
#define argv0 program_invocation_name
|
||||
|
||||
#ifdef ZDEBUG
|
||||
#define zprintf(fmt, ...) \
|
||||
printf(fmt, ## __VA_ARGS__);
|
||||
|
|
@ -23,186 +35,6 @@
|
|||
#define zprintf(...);
|
||||
#endif
|
||||
|
||||
bool print_all_and_quit = false;
|
||||
|
||||
const char* command = NULL;
|
||||
|
||||
struct {
|
||||
bool not;
|
||||
|
||||
bool or, orn, nor;
|
||||
|
||||
bool and, andn, nand;
|
||||
|
||||
bool xor, nxor;
|
||||
|
||||
bool lt, lte, gt, gte;
|
||||
|
||||
bool ternary;
|
||||
} use_operators;
|
||||
|
||||
bool print_truthtable = false;
|
||||
|
||||
bool assume_yes = false;
|
||||
|
||||
bool verbose = false;
|
||||
|
||||
bool print_with_color = false;
|
||||
|
||||
bool print_stats = false;
|
||||
|
||||
bool force_rebuild = false;
|
||||
|
||||
bool quiet = false;
|
||||
|
||||
static void parse_args(int argc, char* const* argv)
|
||||
{
|
||||
bool unset_operators = true;
|
||||
|
||||
print_with_color = isatty(1);
|
||||
|
||||
for (int opt; (opt = getopt(argc, argv, "tpyqmvc:eEo:C:B")) != -1; ) switch (opt)
|
||||
{
|
||||
case 't':
|
||||
print_truthtable = true;
|
||||
break;
|
||||
|
||||
case 'p':
|
||||
print_all_and_quit = true;
|
||||
break;
|
||||
|
||||
case 'y':
|
||||
assume_yes = true;
|
||||
break;
|
||||
|
||||
case 'q':
|
||||
quiet = true;
|
||||
break;
|
||||
|
||||
case 'm':
|
||||
print_stats = true;
|
||||
break;
|
||||
|
||||
case 'v':
|
||||
verbose = true;
|
||||
break;
|
||||
|
||||
case 'c':
|
||||
command = optarg;
|
||||
break;
|
||||
|
||||
case 'E':
|
||||
use_operators.ternary = true;
|
||||
// fallthrough
|
||||
|
||||
case 'e':
|
||||
{
|
||||
use_operators.not = true;
|
||||
use_operators.or = true;
|
||||
use_operators.and = true;
|
||||
|
||||
use_operators.orn = true;
|
||||
use_operators.nor = true;
|
||||
|
||||
use_operators.andn = true;
|
||||
use_operators.nand = true;
|
||||
|
||||
use_operators. xor = true;
|
||||
use_operators.nxor = true;
|
||||
|
||||
unset_operators = false;
|
||||
break;
|
||||
}
|
||||
|
||||
case 'o':
|
||||
{
|
||||
unset_operators = false;
|
||||
|
||||
for (char* moving; (moving = strtok_r(NULL, ",", &optarg)); )
|
||||
{
|
||||
if (!strcmp(moving, "not") || !strcmp(moving, "!"))
|
||||
use_operators.not = true;
|
||||
else if (!strcmp(moving, "or") || !strcmp(moving, "||"))
|
||||
use_operators.or = true;
|
||||
else if (!strcmp(moving, "orn") || !strcmp(moving, "|!"))
|
||||
use_operators.orn = true;
|
||||
else if (!strcmp(moving, "nor") || !strcmp(moving, "!|"))
|
||||
use_operators.nor = true;
|
||||
else if (!strcmp(moving, "and") || !strcmp(moving, "&&"))
|
||||
use_operators.and = true;
|
||||
else if (!strcmp(moving, "andn") || !strcmp(moving, "&!"))
|
||||
use_operators.andn = true;
|
||||
else if (!strcmp(moving, "nand") || !strcmp(moving, "!&"))
|
||||
use_operators.nand = true;
|
||||
else if (!strcmp(moving, "xor") || !strcmp(moving, "!="))
|
||||
use_operators.xor = true;
|
||||
else if (!strcmp(moving, "nxor") || !strcmp(moving, "=="))
|
||||
use_operators.nxor = true;
|
||||
else if (!strcmp(moving, "lt") || !strcmp(moving, "<"))
|
||||
use_operators.lt = true;
|
||||
else if (!strcmp(moving, "lte") || !strcmp(moving, "<="))
|
||||
use_operators.lte = true;
|
||||
else if (!strcmp(moving, "gt") || !strcmp(moving, ">"))
|
||||
use_operators.gt = true;
|
||||
else if (!strcmp(moving, "gte") || !strcmp(moving, ">="))
|
||||
use_operators.gte = true;
|
||||
else if (!strcmp(moving, "ternary") || !strcmp(moving, "?:"))
|
||||
use_operators.ternary = true;
|
||||
else
|
||||
{
|
||||
assert(!"TODO");
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case 'C':
|
||||
{
|
||||
if (!strcmp(optarg, "yes") || !strcmp(optarg, "on"))
|
||||
print_with_color = true;
|
||||
else if (!strcmp(optarg, "no") || !strcmp(optarg, "off"))
|
||||
print_with_color = false;
|
||||
else if (!strcmp(optarg, "auto"))
|
||||
print_with_color = isatty(1);
|
||||
else
|
||||
{
|
||||
assert(!"TODO");
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
case 'B':
|
||||
{
|
||||
force_rebuild = true;
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
{
|
||||
printf("Unknown option '%c'!" "\n", opt);
|
||||
exit(1);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (unset_operators)
|
||||
{
|
||||
use_operators.not = true;
|
||||
use_operators.or = true;
|
||||
use_operators.and = true;
|
||||
}
|
||||
}
|
||||
|
||||
#define W 0b0101010101010101
|
||||
#define X 0b0011001100110011
|
||||
#define Y 0b0000111100001111
|
||||
#define Z 0b0000000011111111
|
||||
#define M 0b1111111111111111
|
||||
|
||||
#define N (65536)
|
||||
|
||||
enum kind {
|
||||
ek_unreachable,
|
||||
|
||||
|
|
@ -1442,15 +1274,18 @@ uint16_t evaluate(const char* text)
|
|||
|
||||
return truthtable;
|
||||
}
|
||||
#endif
|
||||
|
||||
int main(int argc, char* const* argv)
|
||||
{
|
||||
parse_args(argc, argv);
|
||||
ENTER;
|
||||
|
||||
get_simplifications();
|
||||
struct cmdln_flags* flags = process_cmdln_flags(argc, argv);
|
||||
|
||||
if (print_all_and_quit)
|
||||
if (flags->print_all_and_quit)
|
||||
{
|
||||
TODO;
|
||||
#if 0
|
||||
for (int i = 0; i < N; i++)
|
||||
{
|
||||
int cost = lookup[i].cost;
|
||||
|
|
@ -1460,9 +1295,12 @@ int main(int argc, char* const* argv)
|
|||
printf("0b%016b: [%2i]: ", i, cost), print(i, 0), puts("");
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
else if (print_stats)
|
||||
else if (flags->print_stats)
|
||||
{
|
||||
TODO;
|
||||
#if 0
|
||||
printf("statistics:" "\n");
|
||||
|
||||
uintmax_t total_cost = 0;
|
||||
|
|
@ -1515,9 +1353,18 @@ int main(int argc, char* const* argv)
|
|||
{
|
||||
puts("everything unreachable: no statistics to give");
|
||||
}
|
||||
#endif
|
||||
}
|
||||
else if (command)
|
||||
else if (flags->command)
|
||||
{
|
||||
struct scope* scope = new_scope();
|
||||
|
||||
struct simplifications* simplifications = new_simplifications(
|
||||
/* operators: */ &flags->selected_operators,
|
||||
/* scope: */ scope);
|
||||
|
||||
TODO;
|
||||
#if 0
|
||||
uint16_t truthtable = evaluate(command);
|
||||
|
||||
if (print_truthtable)
|
||||
|
|
@ -1534,9 +1381,16 @@ int main(int argc, char* const* argv)
|
|||
// printf("%2i: ", lookup[truthtable].cost), print(truthtable, 0), puts("");
|
||||
print(truthtable, 0), puts("");
|
||||
}
|
||||
#endif
|
||||
|
||||
free_simplifications(simplifications);
|
||||
|
||||
free_scope(scope);
|
||||
}
|
||||
else
|
||||
{
|
||||
TODO;
|
||||
#if 0
|
||||
if (!quiet)
|
||||
{
|
||||
puts("Use C-style syntax for boolean operators and expressions.");
|
||||
|
|
@ -1545,7 +1399,6 @@ int main(int argc, char* const* argv)
|
|||
puts("Comparison operators are also suppported.");
|
||||
}
|
||||
|
||||
|
||||
for (char* line; (line = readline(">>> ")); free(line))
|
||||
{
|
||||
if (!*line) continue;
|
||||
|
|
@ -1567,12 +1420,14 @@ int main(int argc, char* const* argv)
|
|||
{
|
||||
// printf("%2i: ", lookup[truthtable].cost);
|
||||
printf(" ");
|
||||
|
||||
print(truthtable, 0), puts("");
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
free_cmdln_flags(flags);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
|
|||
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue