Пример #1
0
Файл: utf8.c Проект: DeadZen/qse
static QSE_INLINE __utf8_t* get_utf8_slot (qse_wchar_t uc)
{
#if (QSE_SIZEOF_WCHAR_T == QSE_SIZEOF_MCHAR_T)
	/* no utf8 support */

	return QSE_NULL; /* invalid character */

#else
	__utf8_t* cur, * end;

	QSE_ASSERT (QSE_SIZEOF(qse_mchar_t) == 1);
	QSE_ASSERT (QSE_SIZEOF(qse_wchar_t) >= 2);

	end = utf8_table + QSE_COUNTOF(utf8_table);
	cur = utf8_table;

	while (cur < end) 
	{
		if (uc >= cur->lower && uc <= cur->upper) return cur;
		cur++;
	}

	return QSE_NULL; /* invalid character */
#endif
}
Пример #2
0
Файл: rex.c Проект: DeadZen/qse
static qse_rex_node_t* pseudo_group (comp_t* c, qse_rex_node_t* atom)
{
	qse_rex_node_t* g, *ge, * b;

	QSE_ASSERT (atom->occ.min <= 0);

	g = newgroupnode (c);
	if (g == QSE_NULL) return QSE_NULL;

	ge = newgroupendnode (c, g);
	if (ge == QSE_NULL) return QSE_NULL;

	b = newbranchnode (c, atom, ge);
	if (b == QSE_NULL) return QSE_NULL;

	atom->occ.min = 1;
	atom->next = ge;
	QSE_ASSERT (atom->occ.max >= atom->occ.min);

	g->occ.max = 1;
	g->occ.min = 1;
	g->u.g.end = ge;
	g->u.g.head = b;
	g->u.g.pseudo = 1;
	ge->u.ge.pseudo = 1;

	return g;
}
Пример #3
0
	RedBlackTreeNode(const T& value, Color color, SelfType* up, SelfType* left, SelfType* right):
		value (value), color (color), up (up), left (left), right (right)
	{
		QSE_ASSERT (up != this);
		QSE_ASSERT (left != this);
		QSE_ASSERT (right != this);
	}
Пример #4
0
	void clear (bool clear_mpool = false)
	{
		while (this->root->notNil()) this->remove_node (this->root);
		QSE_ASSERT (this->root = this->nil);
		QSE_ASSERT (this->node_count == 0);

		if (clear_mpool) this->mp.dispose ();
	}
Пример #5
0
Файл: mb8.c Проект: DeadZen/qse
qse_size_t qse_mb8towc (
	const qse_mchar_t* utf8, qse_size_t size, qse_wchar_t* wc)
{
	QSE_ASSERT (utf8 != QSE_NULL);
	QSE_ASSERT (size > 0);
	*wc = *(const qse_uint8_t*)utf8;
	return 1;
}
Пример #6
0
	/// The inject() function inserts a \a datum if no existing datum
	/// is found to be equal using the comparator. The \a mode argument
	/// determines what action to take when an equal datum is found.
	/// - -1: failure
	/// -  0: do nothing
	/// -  1: overwrite the existing datum
	///
	/// if \a injected is not #QSE_NULL, it is set to true when \a datum
	/// has been inserted newly and false when an equal datum has been
	/// found.
	///
	/// The function returns the poniter to the node inserted or 
	/// affected. It return #QSE_NULL if mode is set to -1 and a duplicate
	/// item has been found.
	Node* inject (const T& datum, int mode, bool* injected = QSE_NULL)
	{
		Node* x_cur = this->root;
		Node* x_par = this->nil;

		while (x_cur->notNil())
		{
			int n = this->comparator (datum, x_cur->value);
			if (n == 0)
			{
				if (injected) *injected = false;
				if (mode <= -1) return QSE_NULL; // return failure
				if (mode >= 1) x_cur->value = datum;
				return x_cur;
			}

			x_par = x_cur;

			if (n > 0) x_cur = x_cur->right;
			else /* if (n < 0) */ x_cur = x_cur->left;
		}

		Node* x_new = new(&this->mp) Node (datum, Node::RED, this->nil, this->nil, this->nil);
		if (x_par->isNil())
		{
			QSE_ASSERT (this->root->isNil());
			this->root = x_new;
		}
		else
		{
			int n = this->comparator (datum, x_par->value);
			if (n > 0)
			{
				QSE_ASSERT (x_par->right->isNil());
				x_par->right = x_new;
			}
			else
			{
				QSE_ASSERT (x_par->left->isNil());
				x_par->left = x_new;
			}

			x_new->up = x_par;
			this->rebalance_for_injection (x_new);
		}

		this->root->color = Node::BLACK;
		this->node_count++;

		if (injected) *injected = true; // indicate that a new node has been injected
		return x_new;
	}
Пример #7
0
Файл: rex.c Проект: DeadZen/qse
int qse_rex_exec (
	qse_rex_t* rex, const qse_cstr_t* str, 
	const qse_cstr_t* substr, qse_cstr_t* matstr)
{
	exec_t e;
	int n = 0;

	if (rex->code == QSE_NULL)
	{
		rex->errnum = QSE_REX_ENOCOMP;
		return -1;
	}

	QSE_MEMSET (&e, 0, QSE_SIZEOF(e));

	e.rex = rex;
	e.str.ptr = str->ptr;
	e.str.end = str->ptr + str->len;
	e.sub.ptr = substr->ptr;
	e.sub.end = substr->ptr + substr->len;

	if (init_exec_dds (&e, rex->mmgr) <= -1) return -1;

	while (e.sub.ptr <= e.sub.end)
	{
		n = exec (&e);
		if (n <= -1) 
		{
			n = -1;
			break;
		}

		if (n >= 1)
		{
			QSE_ASSERT (e.nmatches > 0);
			QSE_ASSERT (e.matchend != QSE_NULL);
			if (matstr)
			{
				matstr->ptr = e.sub.ptr;
				matstr->len = e.matchend - e.sub.ptr;
			}
			break;
		}

		e.sub.ptr++;
	}

	fini_exec_dds (&e);

	return n;
}
Пример #8
0
Файл: time.c Проект: DeadZen/qse
void qse_subtime (const qse_ntime_t* x, const qse_ntime_t* y, qse_ntime_t* z)
{
	QSE_ASSERT (x->nsec >= 0 && x->nsec < QSE_NSECS_PER_SEC);
	QSE_ASSERT (y->nsec >= 0 && y->nsec < QSE_NSECS_PER_SEC);

	z->sec = x->sec - y->sec;
	z->nsec = x->nsec - y->nsec;

	if (z->nsec < 0)
	{
		z->sec = z->sec - 1;
		z->nsec = z->nsec + QSE_NSECS_PER_SEC;
	}
}
Пример #9
0
Файл: time.c Проект: DeadZen/qse
void qse_addtime (const qse_ntime_t* x, const qse_ntime_t* y, qse_ntime_t* z)
{
	QSE_ASSERT (x->nsec >= 0 && x->nsec < QSE_NSECS_PER_SEC);
	QSE_ASSERT (y->nsec >= 0 && y->nsec < QSE_NSECS_PER_SEC);

	z->sec = x->sec + y->sec;
	z->nsec = x->nsec + y->nsec;

	if (z->nsec >= QSE_NSECS_PER_SEC)
	{
		z->sec = z->sec + 1;
		z->nsec = z->nsec - QSE_NSECS_PER_SEC;
	}
}
Пример #10
0
Файл: rex.c Проект: DeadZen/qse
static group_t* dupgroupstackmembers (exec_t* e, group_t* g)
{
	group_t* yg, * xg = QSE_NULL;

	QSE_ASSERT (g != QSE_NULL);

	if (g->next != QSE_NULL) 
	{
		/* TODO: make it non recursive or 
		 *       implement stack overflow protection */
		xg = dupgroupstackmembers (e, g->next);
		if (xg == QSE_NULL) return QSE_NULL;
	}

	yg = (group_t*) QSE_MMGR_ALLOC (e->rex->mmgr, QSE_SIZEOF(*yg));
	if (yg == QSE_NULL)
	{
		if (xg != QSE_NULL) freegroupstack (xg, e->rex->mmgr);
		e->rex->errnum = QSE_REX_ENOMEM;
		return QSE_NULL;
	}

	QSE_MEMCPY (yg, g, QSE_SIZEOF(*yg));
	yg->next = xg;

	return yg;
}
Пример #11
0
Файл: rex.c Проект: DeadZen/qse
/* duplidate a group stack excluding the top data element */
static group_t* dupgroupstackpop (exec_t* e, group_t* gs)
{
	group_t* dupg, * head;

	QSE_ASSERT (gs != QSE_NULL);
	QSE_ASSERTX (gs->node == QSE_NULL, 
		"The head of a group stack must point to QSE_NULL for management purpose.");
	QSE_ASSERTX (gs->next != QSE_NULL && gs->next->next != QSE_NULL, 
		"dupgroupstackpop() needs at least two data elements");

	dupg = dupgroupstackmembers (e, gs->next->next);
	if (dupg == QSE_NULL) return QSE_NULL;

	head = (group_t*) QSE_MMGR_ALLOC (e->rex->mmgr, QSE_SIZEOF(*head));
	if (head == QSE_NULL)
	{
		if (dupg != QSE_NULL) freegroupstackmembers (dupg, e->rex->mmgr);
		e->rex->errnum = QSE_REX_ENOMEM;
		return QSE_NULL;
	}

	head->node = QSE_NULL;
	head->occ = 0;
	head->next = dupg;

	return head;
}
Пример #12
0
	int operator() (const T& v1, const T& v2) const
	{
		if (v1 > v2) return 1;
		if (v1 < v2) return -1;
		QSE_ASSERT (v1 == v2);
		return 0;
	}
Пример #13
0
Файл: rex.c Проект: DeadZen/qse
static qse_rex_node_t* newnode (comp_t* c, qse_rex_node_id_t id)
{
	qse_rex_node_t* node;

	/* TODO: performance optimization.
	 *       preallocate a large chunk of memory and allocate a node
	 *       from the chunk. increase the chunk if it has been used up.
	 */

	node = (qse_rex_node_t*) 
		QSE_MMGR_ALLOC (c->rex->mmgr, QSE_SIZEOF(qse_rex_node_t));
	if (node == QSE_NULL) 
	{
		c->rex->errnum = QSE_REX_ENOMEM;
		return QSE_NULL;
	}

	QSE_MEMSET (node, 0, QSE_SIZEOF(*node));
	node->id = id;

	if (c->start != QSE_NULL) 
	{
		QSE_ASSERT (c->start->id == QSE_REX_NODE_START);
		node->link = c->start->u.s.link;
		c->start->u.s.link = node;
	}

	return node;
}
Пример #14
0
Файл: rex.c Проект: DeadZen/qse
static void freegroupstack (group_t* gs, qse_mmgr_t* mmgr)
{
	QSE_ASSERT (gs != QSE_NULL);
	QSE_ASSERTX (gs->node == QSE_NULL, 
		"The head of a group stack must point to QSE_NULL for management purpose.");

	freegroupstackmembers (gs, mmgr);
}
Пример #15
0
Файл: tio.c Проект: apense/qse
int qse_tio_attachin (
	qse_tio_t* tio, qse_tio_io_impl_t input,
	qse_mchar_t* bufptr, qse_size_t bufcapa)
{
	qse_mchar_t* xbufptr;

	if (input == QSE_NULL || bufcapa < QSE_TIO_MININBUFCAPA) 
	{
		tio->errnum = QSE_TIO_EINVAL;
		return -1;
	}

	if (qse_tio_detachin(tio) <= -1) return -1;

	QSE_ASSERT (tio->in.fun == QSE_NULL);

	xbufptr = bufptr;
	if (xbufptr == QSE_NULL)
	{
		xbufptr = QSE_MMGR_ALLOC (
			tio->mmgr, QSE_SIZEOF(qse_mchar_t) * bufcapa);
		if (xbufptr == QSE_NULL)
		{
			tio->errnum = QSE_TIO_ENOMEM;
			return -1;	
		}
	}

	tio->errnum = QSE_TIO_ENOERR;
	if (input (tio, QSE_TIO_OPEN, QSE_NULL, 0) <= -1) 
	{
		if (tio->errnum == QSE_TIO_ENOERR) tio->errnum = QSE_TIO_EOTHER;
		if (xbufptr != bufptr) QSE_MMGR_FREE (tio->mmgr, xbufptr);
		return -1;
	}

	/* if i defined tio->io[2] instead of tio->in and tio-out, 
	 * i would be able to shorten code amount. but fields to initialize
	 * are not symmetric between input and output.
	 * so it's just a bit clumsy that i repeat almost the same code
	 * in qse_tio_attachout().
	 */

	tio->in.fun = input;
	tio->in.buf.ptr = xbufptr;
	tio->in.buf.capa = bufcapa;

	tio->status &= ~(STATUS_INPUT_ILLSEQ | STATUS_INPUT_EOF);
	tio->inbuf_cur = 0;
	tio->inbuf_len = 0;

	if (xbufptr != bufptr) tio->status |= STATUS_INPUT_DYNBUF;
	return 0;
}
Пример #16
0
	void __move_to_next_node ()
	{
		QSE_ASSERT (this->current != QSE_NULL);

		while (this->current->notNil())
		{
			if (this->previous == this->current->getUpNode())
			{
				/* the previous node is the parent of the current node.
				 * it indicates that we're going down to the getChild(l) */
				if ((this->current->*this->get_left)()->notNil())
				{
					/* go to the left child */
					this->previous = this->current;
					this->current = (this->current->*this->get_left)();
				}
				else
				{
					this->pending_action = 1;
					break;
				}
			}
			else if (this->previous == (this->current->*this->get_left)())
			{
				/* the left child has been already traversed */
				this->pending_action = 2;
				break;
			}
			else
			{
				/* both the left child and the right child have been traversed */
				QSE_ASSERT (this->previous == (this->current->*this->get_right)());
				/* just move up to the parent */
				this->previous = this->current;
				this->current = this->current->getUpNode();
			}
		}
	}
Пример #17
0
Файл: rex.c Проект: DeadZen/qse
int qse_rex_init (qse_rex_t* rex, qse_mmgr_t* mmgr, qse_rex_node_t* code)
{
	QSE_MEMSET (rex, 0, QSE_SIZEOF(*rex));
	rex->mmgr = mmgr;

	QSE_ASSERT (code == QSE_NULL || code->id == QSE_REX_NODE_START);

	/* note that passing a compiled expression to qse_rex_open() 
	 * is to delegate it to this rex object. when this rex object
	 * is closed, the code delegated is destroyed. */

	rex->code = code;
	return 0;
}
Пример #18
0
Файл: rex.c Проект: DeadZen/qse
static int addsimplecand (
	exec_t* e, group_t* group, qse_rex_node_t* node, 
	qse_size_t occ, const qse_char_t* mptr)
{
	cand_t cand;

	QSE_ASSERT (
		node->id == QSE_REX_NODE_NOP ||
		node->id == QSE_REX_NODE_BOL ||
		node->id == QSE_REX_NODE_EOL ||
		node->id == QSE_REX_NODE_ANY ||
		node->id == QSE_REX_NODE_CHAR ||
		node->id == QSE_REX_NODE_CSET
	);

	cand.node = node;
	cand.occ = occ;
	cand.group = group;
	cand.mptr = mptr;

	if (qse_lda_search (
		&e->cand.set[e->cand.pending],
		0, &cand, 1) != QSE_LDA_NIL)
	{
		/* exclude any existing entries in the array.
		 * see comp_cand() for the equality test used.
		 * note this linear search may be a performance bottle neck	
		 * if the arrary grows large. not so sure if it should be
		 * switched to a different data structure such as a hash table.
		 * the problem is that most practical regular expressions
		 * won't have many candidates for a particular match point.
		 * so i'm a bit skeptical about data struct switching.
		 */
		return 0;
	}

	if (qse_lda_insert (
		&e->cand.set[e->cand.pending],
		QSE_LDA_SIZE(&e->cand.set[e->cand.pending]),
		&cand, 1) == QSE_LDA_NIL)
	{
		e->rex->errnum = QSE_REX_ENOMEM;
		return -1;
	}

	/* the reference must be decremented by the freeer */
	refupgroupstack (group);
	return 0;
}
Пример #19
0
	void rebalance_for_injection (Node* node)
	{
		while (node != this->root)
		{
			Node* tmp, * tmp2, * x_par, * x_grand_par;
			bool leftwise;

			x_par = node->up;
			if (x_par->color == Node::BLACK) break;

			QSE_ASSERT (x_par->up->notNil());

			x_grand_par = x_par->up;
			if (x_par == x_grand_par->left)
			{
				tmp = x_grand_par->right;
				tmp2 = x_par->right;
				leftwise = true;
			}
			else
			{
				tmp = x_grand_par->left;
				tmp2 = x_par->left;
				leftwise = false;
			}

			if (tmp->color == Node::RED)
			{
				x_par->color = Node::BLACK;
				tmp->color = Node::BLACK;
				x_grand_par->color = Node::RED;
				node = x_grand_par;
			}
			else
			{
				if (node == tmp2)
				{
					node = x_par;
					this->rotate (node, leftwise);
					x_par = node->up;
					x_grand_par = x_par->up;
				}

				x_par->color = Node::BLACK;
				x_grand_par->color = Node::RED;
				this->rotate (x_grand_par, !leftwise);
			}
		}
	}
Пример #20
0
static int matchtre (
	qse_awk_t* awk, qse_tre_t* tre, int opt, 
	const qse_cstr_t* str, qse_cstr_t* mat, 
	qse_cstr_t submat[9], qse_awk_errnum_t* errnum)
{
	int n;
	/*qse_tre_match_t match[10] = { { 0, 0 }, };*/
	qse_tre_match_t match[10];

	QSE_MEMSET (match, 0, QSE_SIZEOF(match));
	n = qse_tre_execx(tre, str->ptr, str->len, match, QSE_COUNTOF(match), opt);
	if (n <= -1)
	{
		if (QSE_TRE_ERRNUM(tre) == QSE_TRE_ENOMATCH) return 0;

#if 0 /* TODO: */
		*errnum = (QSE_TRE_ERRNUM(tre) == QSE_TRE_ENOMEM)? 
			QSE_AWK_ENOMEM: QSE_AWK_EREXMA;
		SETERR0 (sed, errnum, loc);
#endif
		*errnum = (QSE_TRE_ERRNUM(tre) == QSE_TRE_ENOMEM)? 
			QSE_AWK_ENOMEM: QSE_AWK_EREXMA;
		return -1;
	}

	QSE_ASSERT (match[0].rm_so != -1);
	if (mat)
	{
		mat->ptr = &str->ptr[match[0].rm_so];
		mat->len = match[0].rm_eo - match[0].rm_so;
	}

	if (submat)
	{
		int i;

		/* you must intialize submat before you pass into this 
		 * function because it can abort filling */
		for (i = 1; i < QSE_COUNTOF(match); i++)
		{
			if (match[i].rm_so != -1) 
			{
				submat[i-1].ptr = &str->ptr[match[i].rm_so];
				submat[i-1].len = match[i].rm_eo - match[i].rm_so;
			}
		}
	}
	return 1;
}
Пример #21
0
Файл: err.c Проект: DeadZen/qse
void qse_xli_seterror (
	qse_xli_t* xli, qse_xli_errnum_t errnum,
	const qse_cstr_t* errarg, const qse_xli_loc_t* errloc)
{
	const qse_char_t* errfmt;

	xli->errnum = errnum;

	errfmt = qse_xli_geterrstr(xli)(xli,xli->errnum);
	QSE_ASSERT (errfmt != QSE_NULL);
	qse_strxfncpy (xli->errmsg, QSE_COUNTOF(xli->errmsg), errfmt, errarg);

	if (errloc != QSE_NULL) xli->errloc = *errloc;
	else QSE_MEMSET (&xli->errloc, 0, QSE_SIZEOF(xli->errloc));
}
Пример #22
0
Файл: rbt.c Проект: DeadZen/qse
static void adjust (rbt_t* rbt, pair_t* pair)
{
	while (pair != rbt->root)
	{
		pair_t* tmp, * tmp2, * x_par;
		int leftwise;

		x_par = pair->parent;
		if (x_par->color == QSE_RBT_BLACK) break;

		QSE_ASSERT (x_par->parent != QSE_NULL);

		if (x_par == x_par->parent->child[LEFT])
		{
			tmp = x_par->parent->child[RIGHT];
			tmp2 = x_par->child[RIGHT];
			leftwise = 1;
		}
		else
		{
			tmp = x_par->parent->child[LEFT];
			tmp2 = x_par->child[LEFT];
			leftwise = 0;
		}

		if (tmp->color == QSE_RBT_RED)
		{
			x_par->color = QSE_RBT_BLACK;
			tmp->color = QSE_RBT_BLACK;
			x_par->parent->color = QSE_RBT_RED;
			pair = x_par->parent;
		}
		else
		{
			if (pair == tmp2)
			{
				pair = x_par;
				rotate (rbt, pair, leftwise);
				x_par = pair->parent;
			}

			x_par->color = QSE_RBT_BLACK;
			x_par->parent->color = QSE_RBT_RED;
			rotate (rbt, x_par->parent, !leftwise);
		}
	}
}
Пример #23
0
Файл: rex.c Проект: DeadZen/qse
static void freeallnodes (qse_rex_node_t* start)
{
	qse_rex_node_t* x, * y;
	qse_mmgr_t* mmgr;

	QSE_ASSERT (start->id == QSE_REX_NODE_START);

	mmgr = start->u.s.mmgr;
	x = start->u.s.link;
	while (x != QSE_NULL)
	{
		y = x; x = x->link;
		freenode (y, mmgr);
	}

	QSE_MMGR_FREE (mmgr, start);
}
Пример #24
0
Файл: rex.c Проект: DeadZen/qse
static group_t* groupstackpop (exec_t* e, group_t* gs)
{
	group_t* top;

	QSE_ASSERT (gs != QSE_NULL);
	QSE_ASSERTX (gs->node == QSE_NULL, 
		"The head of a group stack must point to QSE_NULL for management purpose.");
	QSE_ASSERTX (gs->next != QSE_NULL && gs->next->next != QSE_NULL, 
		"groupstackpop() needs at least two data elements");


	top = gs->next;
	gs->next = top->next;

	QSE_MMGR_FREE (e->rex->mmgr, top);	
	return gs;
}
Пример #25
0
Файл: tio.c Проект: apense/qse
int qse_tio_attachout (
	qse_tio_t* tio, qse_tio_io_impl_t output, 
	qse_mchar_t* bufptr, qse_size_t bufcapa)
{
	qse_mchar_t* xbufptr;

	if (output == QSE_NULL || bufcapa < QSE_TIO_MINOUTBUFCAPA)  
	{
		tio->errnum = QSE_TIO_EINVAL;
		return -1;
	}

	if (qse_tio_detachout(tio) == -1) return -1;

	QSE_ASSERT (tio->out.fun == QSE_NULL);

	xbufptr = bufptr;
	if (xbufptr == QSE_NULL)
	{
		xbufptr = QSE_MMGR_ALLOC (
			tio->mmgr, QSE_SIZEOF(qse_mchar_t) * bufcapa);
		if (xbufptr == QSE_NULL)
		{
			tio->errnum = QSE_TIO_ENOMEM;
			return -1;	
		}
	}

	tio->errnum = QSE_TIO_ENOERR;
	if (output (tio, QSE_TIO_OPEN, QSE_NULL, 0) <= -1) 
	{
		if (tio->errnum == QSE_TIO_ENOERR) tio->errnum = QSE_TIO_EOTHER;
		if (xbufptr != bufptr) QSE_MMGR_FREE (tio->mmgr, xbufptr);
		return -1;
	}

	tio->out.fun = output;
	tio->out.buf.ptr = xbufptr;
	tio->out.buf.capa = bufcapa;

	tio->outbuf_len = 0;

	if (xbufptr != bufptr) tio->status |= STATUS_OUTPUT_DYNBUF;
	return 0;
}
Пример #26
0
		COptional & operator = (COptional const & other)
		{
			QSE_ASSERT( !(this == &other) );	// don't copy over self!
			if (m_bValid)
			{						// first, have to destroy our original.
				m_bValid = false;	// for exception safety if destroy() throws.
				// (big trouble if destroy() throws, though)
				destroy();
			}

			if (other.m_bValid)
			{
				construct( *other );
				m_bValid = true;	// order vital.

			}
			return *this;
		}
Пример #27
0
	RedBlackTreeIterator (Node* root, Mode mode): pending_action (0), current (root)
	{
		QSE_ASSERT (root != QSE_NULL);

		this->previous = root->getUpNode();
		if (mode == DESCENDING)
		{
			this->get_left = &Node::getRightNode;
			this->get_right = &Node::getLeftNode;
		}
		else 
		{
			this->get_left = &Node::getLeftNode;
			this->get_right = &Node::getRightNode;
		}

		this->__move_to_next_node ();
	}
Пример #28
0
Файл: rex.c Проект: DeadZen/qse
static group_t* dupgroupstack (exec_t* e, group_t* gs)
{
	group_t* head;

	QSE_ASSERT (gs != QSE_NULL);
	QSE_ASSERTX (gs->node == QSE_NULL, 
		"The head of a group stack must point to QSE_NULL for management purpose.");

	head = dupgroupstackmembers (e, gs);
	if (head == QSE_NULL) return QSE_NULL;

	QSE_ASSERTX (
		head->node == QSE_NULL && 
		head->node == gs->node && 
		head->occ == gs->occ,
		"The duplicated stack head must not be corrupted"
	);

	/* reset the reference count of a duplicated stack */
	head->occ = 0;
	return head;
}
Пример #29
0
Файл: rex.c Проект: DeadZen/qse
static int charset (comp_t* com, qse_rex_node_t* node)
{
	QSE_ASSERT (node->id == QSE_REX_NODE_CSET);
	QSE_ASSERT (node->u.cset.negated == 0);
	QSE_ASSERT (node->u.cset.member	== QSE_NULL);

	if (IS_SPE(com,QSE_T('^')))
	{
		/* negate an expression */
		node->u.cset.negated = 1;
		if (getc_noesc(com) <= -1) return -1;
	}


	/* initialize the member array */
	node->u.cset.member = qse_str_open (com->rex->mmgr, 0, 64);
	if (node->u.cset.member == QSE_NULL)
	{
		com->rex->errnum = QSE_REX_ENOMEM;
		return -1;
	}

	/* if ] is the first character or the second character following ^,
	 * it is treated literally */

	do
	{
		int x1, x2;
		qse_char_t c1, c2;

		x1 = com->c.escaped;
		c1 = com->c.value;
		if (c1 == QSE_CHAR_EOF)
		{
			com->rex->errnum = QSE_REX_EPREEND;
			return -1;
		}

		if (getc_esc(com) <= -1) return -1;
		x2 = com->c.escaped;
		c2 = com->c.value;

		if (!x1 && c1 == QSE_T('[') && 
		    !x2 && c2 == QSE_T(':'))
		{
			int n;
			qse_char_t tmp[2];

			/* begins with [: 
			 * don't read in the next character as charclass() 
			 * matches a class name differently from other routines.
			 * if (getc_noesc(com) <= -1) return -1;
			 */
			if ((n = charclass(com)) <= -1) return -1;
			
			QSE_ASSERT (n < QSE_TYPE_MAX(qse_char_t));

			tmp[0] = QSE_REX_CSET_CLASS;
			tmp[1] = n;
			ADD_CSET_CODE (com, node, tmp, QSE_COUNTOF(tmp));
		}
		else if (!x2 && c2 == QSE_T('-'))
		{
			if (getc_esc(com) <= -1) return -1;
			if (IS_SPE(com, QSE_T(']')))
			{
				qse_char_t tmp[4];

				/* '-' is the last character in the set.
				 * treat it literally */

				tmp[0] = QSE_REX_CSET_CHAR;
				tmp[1] = c1;
				tmp[2] = QSE_REX_CSET_CHAR;
				tmp[3] = c2;

				ADD_CSET_CODE (com, node, tmp, QSE_COUNTOF(tmp));
				break;
			}

			if (c1 > com->c.value)
			{
				/* range end must be >= range start */
				com->rex->errnum = QSE_REX_ECRANGE;
				return -1;
			}
			else if (c1 == com->c.value)
			{
				/* if two chars in the range are the same,
				 * treat it as a single character */
				qse_char_t tmp[2];
				tmp[0] = QSE_REX_CSET_CHAR;
				tmp[1] = c1;
				ADD_CSET_CODE (com, node, tmp, QSE_COUNTOF(tmp));
			}
			else
			{
				qse_char_t tmp[3];
				tmp[0] = QSE_REX_CSET_RANGE;
				tmp[1] = c1;
				tmp[2] = com->c.value;
				ADD_CSET_CODE (com, node, tmp, QSE_COUNTOF(tmp));
			}
			
			if (getc_esc(com) <= -1) return -1;
		}
		else
		{
			qse_char_t tmp[2];
			tmp[0] = QSE_REX_CSET_CHAR;
			tmp[1] = c1;
			ADD_CSET_CODE (com, node, tmp, QSE_COUNTOF(tmp));
		}
	}
	while (!IS_SPE(com,QSE_T(']')));

	if (getc_esc(com) <= -1) return -1;
	return 0;
}
Пример #30
0
Файл: rex.c Проект: DeadZen/qse
static void refdowngroupstack_incand (qse_lda_t* lda, void* dptr, qse_size_t dlen)
{
	QSE_ASSERT (dlen == 1);
	refdowngroupstack (((cand_t*)dptr)->group, lda->mmgr);
}