*/ 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; }
*/ 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; }