예제 #1
0
*/	REBVAL *Append_Event()
/*
**		Append an event to the end of the current event port queue.
**		Return a pointer to the event value.
**
**		Note: this function may be called from out of environment,
**		so do NOT extend the event queue here. If it does not have
**		space, return 0. (Should it overwrite or wrap???)
**
***********************************************************************/
{
	REBVAL *port;
	REBVAL *value;
	REBVAL *state;

	port = Get_System(SYS_PORTS, PORTS_SYSTEM);
	if (!IS_PORT(port)) return 0; // verify it is a port object

	// Get queue block:
	state = VAL_BLK_SKIP(port, STD_PORT_STATE);
	if (!IS_BLOCK(state)) return 0;

	// Append to tail if room:
	if (SERIES_FULL(VAL_SERIES(state))) Crash(RP_MAX_EVENTS);
	VAL_TAIL(state)++;
	value = VAL_BLK_TAIL(state);
	SET_END(value);
	value--;
	SET_NONE(value);

	//Dump_Series(VAL_SERIES(state), "state");
	//Print("Tail: %d %d", VAL_TAIL(state), nn++);

	return value;
}
예제 #2
0
*/	REBCNT Make_Word(REBYTE *str, REBCNT len)
/*
**		Given a string and its length, compute its hash value,
**		search for a match, and if not found, add it to the table.
**		Length of zero indicates you provided a zero terminated string.
**		Return the table index for the word (whether found or new).
**
***********************************************************************/
{
	REBINT	hash;
	REBINT	size;
	REBINT	skip;
	REBINT	n;
	REBCNT	h;
	REBCNT	*hashes;
	REBVAL  *words;
	REBVAL  *w;

	//REBYTE *sss = Get_Sym_Name(1);	// (Debugging method)

	if (len == 0) len = LEN_BYTES(str);

	// If hash part of word table is too dense, expand it:
	if (PG_Word_Table.series->tail > PG_Word_Table.hashes->tail/2)
		Expand_Word_Table();

	ASSERT((SERIES_TAIL(PG_Word_Table.series) == SERIES_TAIL(Bind_Table)), RP_BIND_TABLE_SIZE);

	// If word symbol part of word table is full, expand it:
	if (SERIES_FULL(PG_Word_Table.series)) {
		Extend_Series(PG_Word_Table.series, 256);
	}
	if (SERIES_FULL(Bind_Table)) {
		Extend_Series(Bind_Table, 256);
		CLEAR_SERIES(Bind_Table);
	}

	size   = (REBINT)PG_Word_Table.hashes->tail;
	words  = BLK_HEAD(PG_Word_Table.series);
	hashes = (REBCNT *)PG_Word_Table.hashes->data;

	// Hash the word, including a skip factor for lookup:
	hash  = Hash_Word(str, len);
	skip  = (hash & 0x0000FFFF) % size;
	if (skip == 0) skip = 1;
	hash = (hash & 0x00FFFF00) % size;
	//Debug_Fmt("%s hash %d skip %d", str, hash, skip);

	// Search hash table for word match:
	while (NZ(h = hashes[hash])) {
		while ((n = Compare_UTF8(VAL_SYM_NAME(words+h), str, len)) >= 0) {
			//if (Match_String("script", str, len))
			//	Debug_Fmt("---- %s %d %d\n", VAL_SYM_NAME(&words[h]), n, h);
			if (n == 0) return h; // direct hit
			if (VAL_SYM_ALIAS(words+h)) h = VAL_SYM_ALIAS(words+h);
			else goto make_sym; // Create new alias for word
		}
		hash += skip;
		if (hash >= size) hash -= size;
	}

make_sym:
	n = PG_Word_Table.series->tail;
	w = words + n;
	if (h) {
		// Alias word (h = canon word)
		VAL_SYM_ALIAS(words+h) = n;
		VAL_SYM_CANON(w) = VAL_SYM_CANON(words+h);
	} else {
		// Canon (base version of) word (h == 0)
		hashes[hash] = n;
		VAL_SYM_CANON(w) = n;
	}
	VAL_SYM_ALIAS(w) = 0;
	VAL_SYM_NINDEX(w) = Make_Word_Name(str, len);
	VAL_SET(w, REB_HANDLE);

	// These are allowed because of the SERIES_FULL checks above which
	// add one extra to the TAIL check comparision. However, their
	// termination values (nulls) will be missing.
	PG_Word_Table.series->tail++;
	Bind_Table->tail++;

	return n;
}