Exemple #1
0
static caddr_t
bif_mts_enlist_transaction (caddr_t * qst, caddr_t * err_ret,
    state_slot_t ** args)
{
  /* get encoded transaction cookie */
  caddr_t tr_cookie_str =
      bif_string_arg (qst, args, 0, "mts_enlist_transaction");
  caddr_t tr_cookie;
  unsigned long len;

  if (!stricmp(tr_cookie_str,"LOCAL"))
    {
      /* should be changed */
      dbg_printf(("retire lt=%x\n",((query_instance_t*)QST_INSTANCE(qst))->qi_trx));
      tp_retire((query_instance_t*)QST_INSTANCE(qst));
      return box_num (0);
    }
  dbg_printf(("enlisting...\n"));

  if (export_mts_bin_decode (tr_cookie_str, &tr_cookie, &len) == -1)
    sqlr_error("MX001", "could not decode transaction cookie");

  if (mts_trx_enlist (QI_TRX (QST_INSTANCE (qst)), tr_cookie, len))
    {
      dk_free (tr_cookie, -1);
      sqlr_error("MX002", "could not enlist in transaction (%s)",tr_cookie_str);
    };

  dk_free (tr_cookie, -1);
  return box_num (0);
}
semaphore_t *
semaphore_allocate (int entry_count)
{
  NEW_VAR (pthread_mutex_t, ptm);
  NEW_VAR (semaphore_t, sem);
  int rc;

  memset ((void *) ptm, 0, sizeof (pthread_mutex_t));
#ifndef OLD_PTHREADS
  rc = pthread_mutex_init (ptm, &_mutex_attr);
#else
  rc = pthread_mutex_init (ptm, _mutex_attr);
#endif
  CKRET (rc);

  sem->sem_entry_count = entry_count;
  sem->sem_handle = (void *) ptm;
#ifdef SEM_NO_ORDER
  sem->sem_cv = _alloc_cv ();
  if (!sem->sem_cv) goto failed;
  sem->sem_any_signalled = 0;
#endif
  thread_queue_init (&sem->sem_waiting);
  return sem;

failed:
  dk_free ((void *) ptm, sizeof (pthread_mutex_t));
  dk_free (sem, sizeof (semaphore_t));
  return NULL;
}
void
semaphore_free (semaphore_t *sem)
{
  pthread_mutex_destroy ((pthread_mutex_t*) sem->sem_handle);
  dk_free (sem->sem_handle, sizeof (pthread_mutex_t));
#ifdef SEM_NO_ORDER
  dk_free (sem->sem_cv, sizeof (pthread_cond_t));
#endif
  dk_free (sem, sizeof (semaphore_t));
}
int
DBG_HASHEXT_NAME(id_casemode_hash_remove) (DBG_PARAMS id_hash_t * ht, caddr_t _qn, caddr_t _o)
{
  id_casemode_entry_llist_t **list;

  list = (id_casemode_entry_llist_t **) id_hash_get (ht, (caddr_t) &_qn);

  if (list && *list)
    {
      id_casemode_entry_llist_t seed;
      id_casemode_entry_llist_t *iter = &seed;
      seed.next = *list;
      while (iter->next)
	{
	  if (casemode_strhashcmp ((char *) &(iter->next->owner), (char *) &_o))
	    {
	      id_casemode_entry_llist_t *to_delete = iter->next;
	      iter->next = iter->next->next;
	      dk_free (to_delete, sizeof (id_casemode_entry_llist_t));
	      *list = seed.next;
	      return 1;
	    }
	  iter = iter->next;
	}
    }
  return 0;
}
Exemple #5
0
void
free_RM (mts_RM_t ** prm)
{
  mts_RM_t *rm = *prm;
  if (rm->rm)
    {
      rm->rm->Release ();
      rm->rm = 0;
    };
  if (rm->rmcookie)
    {
      dk_free (rm->rmcookie, rm->rmcookie_len);
      rm->rmcookie = 0;
    };
  if (rm->trx_dispenser)
    {
      rm->trx_dispenser->Release ();
      rm->trx_dispenser = 0;
    };
  if (rm->trx_import)
    {
      rm->trx_import->Release ();
      rm->trx_import = 0;
    };
  rm = 0;
}
Exemple #6
0
void
CTransactResourceAsync::operator
delete (void *p)
{
    MTS_TRACE (("TRA::operator delete\n"));
    dk_free (p, -1);
}
void
semaphore_free (semaphore_t *sem)
{
  thread_t *thr;

  while ((thr = thread_queue_from (&sem->sem_waiting)) != NULL)
    _fiber_status (thr, RUNNABLE);

  dk_free (sem, sizeof (semaphore_t));
}
Exemple #8
0
void
mts_trx_free (mts_t * trx)
{
  if (trx->mts_trx)
    trx->mts_trx->Release ();
  if (trx->mts_enlistment)
    trx->mts_enlistment->Release ();

  dk_free (trx, sizeof (mts_t));
};
void
mutex_free (dk_mutex_t *mtx)
{
  semaphore_free ((semaphore_t *) mtx->mtx_handle);
#ifdef MTX_DEBUG
  dk_free_box (mtx->mtx_name);
#endif
  dk_free (mtx, sizeof (dk_mutex_t));
  dk_set_delete (&all_mtxs, (void*) mtx);
}
void
free_attr_array (vxml_parser_t * parser)
{
  int ctr = parser->attrdata.local_attrs_count;
  while (ctr--)
    {
      tag_attr_t * att = parser->tmp.attr_array+ctr;
      dk_free (att->ta_raw_name.lm_memblock, -1);
      dk_free_box (att->ta_value);
    }
  parser->attrdata.local_attrs_count = 0;
}
dk_mutex_t *
mutex_allocate_typed (int type)
{
  int rc;
  static int is_initialized = 0;
  NEW_VARZ (dk_mutex_t, mtx);
  mtx->mtx_type = type;
#if HAVE_SPINLOCK
  if (MUTEX_TYPE_SPIN == type)
    {
      pthread_spin_init (&mtx->l.spinl, 0);
    }
  else
#endif
    {
      memset ((void *) &mtx->mtx_mtx, 0, sizeof (pthread_mutex_t));
#ifndef OLD_PTHREADS
      if (!is_initialized)
	{
	  pthread_mutexattr_init (&_mutex_attr);
#if defined (PTHREAD_PROCESS_PRIVATE) && !defined(oldlinux) && !defined (__FreeBSD__)	  
	  rc = pthread_mutexattr_setpshared (&_mutex_attr, PTHREAD_PROCESS_PRIVATE);
	  CKRET (rc);
#endif

#ifdef PTHREAD_ADAPTIVE_MUTEX_INITIALIZER_NP
	  rc = pthread_mutexattr_settype (&_mutex_attr, PTHREAD_MUTEX_ADAPTIVE_NP);
	  CKRET (rc);
#endif
	  is_initialized = 1;
	}
      rc = pthread_mutex_init (&mtx->mtx_mtx, &_mutex_attr);
#else
      rc = pthread_mutex_init (&mtx->mtx_mtx, _mutex_attr);
#endif
      CKRET (rc);
    }
#ifdef MTX_DEBUG
  mtx->mtx_owner = NULL;
#endif
#ifdef MTX_METER
  if (all_mtxs_mtx)
    mutex_enter (all_mtxs_mtx);
  dk_set_push (&all_mtxs, (void*)mtx);
  if (all_mtxs_mtx)
    mutex_leave (all_mtxs_mtx);
#endif
  return mtx;

failed:
  dk_free (mtx, sizeof (dk_mutex_t));
  return NULL;
}
thread_t *
thread_attach (void)
{
  thread_t *thr;
  int rc;

  thr = thread_alloc ();
  thr->thr_stack_size = (unsigned long) -1;
  thr->thr_attached = 1;
  if (thr->thr_cv == NULL)
    goto failed;

  *((pthread_t *) thr->thr_handle) = pthread_self ();

  rc = pthread_setspecific (_key_current, thr);
  CKRET (rc);

  /* Store the context so we can easily restart a dead thread */
  setjmp (thr->thr_init_context);

  thr->thr_status = RUNNING;
  _thread_init_attributes (thr);
  thr->thr_stack_base = 0;

  return thr;

failed:
  if (thr->thr_sem)
    semaphore_free (thr->thr_sem);
  if (thr->thr_schedule_sem)
    semaphore_free (thr->thr_schedule_sem);
  if (thr->thr_handle)
    dk_free (thr->thr_handle, sizeof (pthread_t));
  dk_free (thr, sizeof (thread_t));
  return NULL;
}
/*
 *  Allocates a condition variable
 */
static void *
_alloc_cv (void)
{
  NEW_VAR (pthread_cond_t, cv);
  int rc;

  memset ((void *) cv, 0, sizeof (pthread_cond_t));
#ifndef OLD_PTHREADS
  rc = pthread_cond_init (cv, NULL);
#else
  rc = pthread_cond_init (cv, pthread_condattr_default);
#endif
  CKRET (rc);

  return (void *) cv;

failed:
  dk_free ((void *) cv, sizeof (pthread_cond_t));
  return NULL;
}
Exemple #14
0
void *
basket_get (basket_t * bsk)
{
  void *data;

#ifdef MTX_DEBUG
  if (bsk->bsk_req_mtx)
    ASSERT_IN_MTX (bsk->bsk_req_mtx);
#endif
  if (bsk->bsk_count == 0)
    return NULL;

  bsk->bsk_count--;
  bsk = bsk->bsk_next;

  LISTDELETE (bsk, bsk_next, bsk_prev);

  data = bsk->bsk_pointer;
  dk_free (bsk, sizeof (basket_t));

  return data;
}
void
DBG_HASHEXT_NAME(id_casemode_hash_free) (DBG_PARAMS id_hash_t * hash)
{
  id_hash_iterator_t hit;
  char *kp;
  char *dp;

  id_hash_iterator (&hit, hash);
  while (hit_next (&hit, &kp, &dp))
    {
      if (dp)
	{
	  id_casemode_entry_llist_t *iter = *(id_casemode_entry_llist_t **) dp;
	  while (iter)
	    {
	      id_casemode_entry_llist_t *iter_next = iter->next;
	      dk_free (iter, sizeof (id_casemode_entry_llist_t));
	      iter = iter_next;
	    }
	}
    }
  DBG_HASHEXT_NAME(id_hash_free) (DBG_ARGS hash);
}
void
mutex_free (dk_mutex_t *mtx)
{
#if HAVE_SPINLOCK
  if (MUTEX_TYPE_SPIN == mtx->mtx_type)
    {
      pthread_spin_destroy (&mtx->l.spinl);
    }
  else
#endif
    {
      pthread_mutex_destroy ((pthread_mutex_t*) &mtx->mtx_mtx);
    }
#ifdef MTX_DEBUG
  dk_free_box (mtx->mtx_name);
#endif
#ifdef MTX_METER
  mutex_enter (all_mtxs_mtx);
  dk_set_delete (&all_mtxs, (void*) mtx);
  mutex_leave (all_mtxs_mtx);
#endif
  dk_free (mtx, sizeof (dk_mutex_t));
}
int
pop_tag (vxml_parser_t * parser)
{
  int ns_ctr;
  opened_tag_t *tag = parser->inner_tag;
  if (tag == parser->tag_stack_holder)
    return 0;
  ns_ctr = parser->attrdata.all_nsdecls_count;
  while (ns_ctr--)
    {
      nsdecl_t *ns = parser->nsdecl_array + ns_ctr;
      if (ns->nsd_tag < parser->inner_tag)
	break;
      dk_free_box (ns->nsd_prefix);
      dk_free_box (ns->nsd_uri);
    }
  parser->attrdata.all_nsdecls_count = ns_ctr + 1;
  dk_free (tag->ot_name.lm_memblock, -1);
  parser->inner_tag--;
  if (tag == parser->tag_stack_holder)
    CLR_STATE(XML_A_CHAR);
  return 1;
}
Exemple #18
0
void
mts_trx_dealloc (struct tp_dtrx_s *dtrx)
{
  mts_trx_free ((mts_t *) dtrx->dtrx_info);
  dk_free (dtrx, sizeof (tp_dtrx_t));
}
void
thread_exit (int n)
{
  thread_t *thr = current_thread;
  volatile int is_attached = thr->thr_attached;

  if (thr == _main_thread)
    {
      call_exit (n);
    }

  thr->thr_retcode = n;
  thr->thr_status = DEAD;

  if (is_attached)
    {
      thr->thr_status = TERMINATE;
      goto terminate;
    }

  Q_LOCK ();
  thread_queue_to (&_deadq, thr);
  _thread_num_dead++;

  do
    {
      int rc = pthread_cond_wait ((pthread_cond_t *) thr->thr_cv, (pthread_mutex_t*) &_q_lock->mtx_mtx);
      CKRET (rc);
    } while (thr->thr_status == DEAD);
  Q_UNLOCK ();

  if (thr->thr_status == TERMINATE)
    goto terminate;
  /* Jumps back into _thread_boot */
  longjmp (thr->thr_init_context, 1);

failed:
  thread_queue_remove (&_deadq, thr);
  _thread_num_dead--;
  Q_UNLOCK ();
terminate:
  if (thr->thr_status == TERMINATE)
    {
#ifndef OLD_PTHREADS
      pthread_detach (* (pthread_t *)thr->thr_handle);
#else
      pthread_detach ( (pthread_t *)thr->thr_handle);
#endif
      _thread_free_attributes (thr);
      dk_free ((void *) thr->thr_cv, sizeof (pthread_cond_t));
      semaphore_free (thr->thr_sem);
      semaphore_free (thr->thr_schedule_sem);
      dk_free (thr->thr_handle, sizeof (pthread_t));
      thr_free_alloc_cache (thr);
      dk_free (thr, sizeof (thread_t));
    }
  if (!is_attached)
    {
      _thread_num_total--;
      pthread_exit ((void *) 1L);
    }
}
thread_t *
thread_create (
    thread_init_func initial_function,
    unsigned long stack_size,
    void *initial_argument)
{
  thread_t *thr;
  int rc;

  assert (_main_thread != NULL);

  if (stack_size == 0)
    stack_size = THREAD_STACK_SIZE;

#if (SIZEOF_VOID_P == 8)
  stack_size *= 2;
#endif
#if defined (__x86_64 ) && defined (SOLARIS)
  /*GK: the LDAP on that platform requires that */
  stack_size *= 2;
#endif
#ifdef HPUX_ITANIUM64
  stack_size += 8 * 8192;
#endif

  stack_size = ((stack_size / 8192) + 1) * 8192;

#if defined (PTHREAD_STACK_MIN)
  if (stack_size < PTHREAD_STACK_MIN)
    {
      stack_size = PTHREAD_STACK_MIN;
    }
#endif
  /* Any free threads with the right stack size? */
  Q_LOCK ();
  for (thr = (thread_t *) _deadq.thq_head.thr_next;
       thr != (thread_t *) &_deadq.thq_head;
       thr = (thread_t *) thr->thr_hdr.thr_next)
    {
      /* if (thr->thr_stack_size >= stack_size) */
	break;
    }
  Q_UNLOCK ();

  /* No free threads, create a new one */
  if (thr == (thread_t *) &_deadq.thq_head)
    {
#ifndef OLD_PTHREADS
      size_t os_stack_size = stack_size;
#endif
      thr = thread_alloc ();
      thr->thr_initial_function = initial_function;
      thr->thr_initial_argument = initial_argument;
      thr->thr_stack_size = stack_size;
      if (thr->thr_cv == NULL)
	goto failed;

#ifdef HPUX_ITANIUM64
      if (stack_size > PTHREAD_STACK_MIN)
        {
	  size_t s, rses;
          pthread_attr_getstacksize (&_thread_attr, &s);
	  pthread_attr_getrsestacksize_np (&_thread_attr, &rses);
	  log_error ("default rses=%d stack=%d : %m", rses,s);
	}
#endif


#ifndef OLD_PTHREADS
# if  defined(HAVE_PTHREAD_ATTR_SETSTACKSIZE)
      rc = pthread_attr_setstacksize (&_thread_attr, stack_size);
      if (rc)
	{
          log_error ("Failed setting the OS thread stack size to %d : %m", stack_size);
	}
# endif

#if defined(HAVE_PTHREAD_ATTR_GETSTACKSIZE)
      if (0 == pthread_attr_getstacksize (&_thread_attr, &os_stack_size))
	{
	  if (os_stack_size > 4 * 8192)
	    stack_size = thr->thr_stack_size = ((unsigned long) os_stack_size) - 4 * 8192;
	}
#endif
#ifdef HPUX_ITANIUM64
      if (stack_size > PTHREAD_STACK_MIN)
        {
	  size_t rsestack_size = stack_size / 2;
          rc = pthread_attr_setrsestacksize_np (&_thread_attr, rsestack_size);
	  if (rc)
	    {
	      log_error ("Failed setting the OS thread 'rse' stack size to %d (plain stack size set to %d) : %m", rsestack_size, stack_size);
	    }
	  thr->thr_stack_size /= 2;
	}
#endif

      rc = pthread_create ((pthread_t *) thr->thr_handle, &_thread_attr,
	  _thread_boot, thr);
      CKRET (rc);

      /* rc = pthread_detach (*(pthread_t *) thr->thr_handle); */
      /* CKRET (rc); */

#else /* OLD_PTHREAD */
      rc = pthread_attr_setstacksize (&_thread_attr, stack_size);
      CKRET (rc);

      rc = pthread_create ((pthread_t *) thr->thr_handle, _thread_attr,
	  _thread_boot, thr);
      CKRET (rc);

      /* rc = pthread_detach ((pthread_t *) thr->thr_handle); */
      /* CKRET (rc); */
#endif

      _thread_num_total++;
#if 0
      if (DO_LOG(LOG_THR))
	log_info ("THRD_0 OS threads create (%i)", _thread_num_total);
#endif
      thread_set_priority (thr, NORMAL_PRIORITY);
    }
  else
    {
      Q_LOCK ();
      thread_queue_remove (&_deadq, thr);
      _thread_num_dead--;
      Q_UNLOCK ();
      assert (thr->thr_status == DEAD);
      /* Set new context for the thread and resume it */
      thr->thr_initial_function = initial_function;
      thr->thr_initial_argument = initial_argument;
      thr->thr_status = RUNNABLE;
      rc = pthread_cond_signal ((pthread_cond_t *) thr->thr_cv);
      CKRET (rc);
/*    if (DO_LOG(LOG_THR))
	log_info ("THRD_3 OS threads reuse. Info threads - total (%ld) wait (%ld) dead (%ld)",
            _thread_num_total, _thread_num_wait, _thread_num_dead);*/
    }

  return thr;

failed:
  if (thr->thr_status == RUNNABLE)
    {
      _thread_free_attributes (thr);
      dk_free (thr, sizeof (thread_t));
    }
  return NULL;
}
/*
 *  The main thread must call this function to convert itself into a thread.
 */
thread_t *
thread_initial (unsigned long stack_size)
{
  int rc;
  thread_t *thr = NULL;

  if (_main_thread)
    return _main_thread;

  /*
   *  Initialize pthread key
   */
#ifndef OLD_PTHREADS
  rc = pthread_key_create (&_key_current, NULL);
#else
  rc = pthread_keycreate (&_key_current, NULL);
#endif
  CKRET (rc);

  /*
   *  Start off with a value of NULL
   */
  rc = pthread_setspecific (_key_current, NULL);
  CKRET (rc);

  /*
   *  Initialize default thread/mutex attributes
   */
#ifndef OLD_PTHREADS
  /* attribute for thread creation */
  rc = pthread_attr_init (&_thread_attr);
  CKRET (rc);

  /* attribute for mutex creation */
  rc = pthread_mutexattr_init (&_mutex_attr);
  CKRET (rc);
#else
  rc = pthread_attr_create (&_thread_attr);
  CKRET (rc);

  rc = pthread_mutexattr_create (&_mutex_attr);
  CKRET (rc);
#endif

#if defined (PTHREAD_PROCESS_PRIVATE) && !defined(oldlinux) && !defined(__FreeBSD__)
  rc = pthread_mutexattr_setpshared (&_mutex_attr, PTHREAD_PROCESS_PRIVATE);
  CKRET (rc);
#endif

#if defined (MUTEX_FAST_NP) && !defined (_AIX)
  rc = pthread_mutexattr_setkind_np (&_mutex_attr, MUTEX_FAST_NP);
  CKRET (rc);
#endif

#ifdef PTHREAD_ADAPTIVE_MUTEX_INITIALIZER_NP
  rc = pthread_mutexattr_settype (&_mutex_attr, PTHREAD_MUTEX_ADAPTIVE_NP);
  CKRET (rc);
#endif

  /*
   *  Allocate a thread structure
   */
  thr = (thread_t *) dk_alloc (sizeof (thread_t));
  memset (thr, 0, sizeof (thread_t));

  assert (_main_thread == NULL);
  _main_thread = thr;

  _sched_init ();

  if (stack_size == 0)
    stack_size = MAIN_STACK_SIZE;

#if (SIZEOF_VOID_P == 8)
  stack_size *= 2;
#endif
#if defined (__x86_64 ) && defined (SOLARIS)
  /*GK: the LDAP on that platform requires that */
  stack_size *= 2;
#endif


  stack_size = ((stack_size / 8192) + 1) * 8192;

  thr->thr_stack_size = stack_size;
  thr->thr_status = RUNNING;
  thr->thr_cv = _alloc_cv ();
  thr->thr_sem = semaphore_allocate (0);
  thr->thr_schedule_sem = semaphore_allocate (0);
  if (thr->thr_cv == NULL)
    goto failed;
  _thread_init_attributes (thr);
  thread_set_priority (thr, NORMAL_PRIORITY);

  rc = pthread_setspecific (_key_current, thr);
  CKRET (rc);

  return thr;

failed:
  if (thr)
    {
      _thread_free_attributes (thr);
      dk_free (thr, sizeof (thread_t));
    }
  return NULL;
}
void LH_ITERATE_WORDS_NAME(const unichar *buf, size_t bufsize, lh_word_check_t *check, lh_word_callback_t *callback, void *userdata)
{
  size_t pos = 0;
  size_t word_start;
  size_t word_length;
  utf8char word_buf[BUFSIZEOF__UTF8_WORD];
  utf8char *hugeword_buf = NULL;
  size_t hugeword_buf_size = 0;
  utf8char *word_end;
  int prop;
#ifdef LH_ITERATOR_DEBUG
  int wordctr = 0, wordcount = LH_COUNT_WORDS_NAME (buf, bufsize, check);
#define wordctr_INC1 wordctr++
#else
#define wordctr_INC1
#endif
  while (pos < bufsize)
    {
      prop = UNICHAR_GETPROPS_EXPN (buf, bufsize, pos);
      if (prop & UCP_ALPHA)
	{
	  word_start = pos;
	  do pos++; while ((pos < bufsize) && (UNICHAR_GETPROPS_EXPN (buf, bufsize, pos) & UCP_ALPHA));
	  word_length = pos - word_start;
	  if (WORD_MAX_CHARS < word_length)
	    continue;
	  if (NULL!=check && 0 == check(buf+word_start, word_length))
	    continue;
	  word_end = (utf8char *)eh_encode_buffer__UTF8 (buf+word_start, buf+pos, (char *)word_buf, (char *)(word_buf+BUFSIZEOF__UTF8_WORD));
	  if (NULL != word_end)
	    {
	      callback (word_buf, word_end-word_buf, userdata);
              wordctr_INC1;
	      continue;
	    }
	  if (hugeword_buf_size<(word_length*MAX_UTF8_CHAR))
	    {
	      if (hugeword_buf_size)
		dk_free (hugeword_buf, hugeword_buf_size);
	      hugeword_buf_size = word_length*MAX_UTF8_CHAR;
	      hugeword_buf = (utf8char *) dk_alloc (hugeword_buf_size);
	    }
	  word_end = (utf8char *)eh_encode_buffer__UTF8 (buf+word_start, buf+pos, (char *)hugeword_buf, (char *)(hugeword_buf+hugeword_buf_size));
	  callback (hugeword_buf, word_end-hugeword_buf, userdata);
          wordctr_INC1;
	  continue;
	}
      if (prop & UCP_IDEO)
	{
	  word_start = pos;
	  pos++;
	  if (NULL!=check && 0 == check(buf+pos-1, 1))
	    continue;
	  word_end = (utf8char *)eh_encode_buffer__UTF8 (buf+word_start, buf+pos, (char *)(word_buf), (char *)(word_buf+BUFSIZEOF__UTF8_WORD));
	  callback (word_buf, word_end-word_buf, userdata);
          wordctr_INC1;
	  continue;
	}
      pos++;
    }
  if (hugeword_buf_size)
    dk_free (hugeword_buf, hugeword_buf_size);
#ifdef LH_ITERATOR_DEBUG
  if (wordctr != wordcount)
    GPF_T;
#endif
}
int elh_iterate_patched_words__xany__UTF8(const char *buf, size_t bufsize, lh_word_check_t *check, lh_word_patch_t *patch, lh_word_callback_t *callback, void *userdata)
{
  unichar check_buf[WORD_MAX_CHARS];
  int prop;
  const char *curr = buf;
  const char *buf_end = buf+bufsize;
  const char *word_begin = curr;
  const char *word_end = NULL;
  unichar uchr;
  size_t word_length;
  unichar patch_buf[WORD_MAX_CHARS];
  const unichar *arg_begin;
  size_t arg_length;
  char word_buf[BUFSIZEOF__UTF8_WORD];
  char *hugeword_buf = NULL;
  size_t hugeword_buf_size = 0;
  while (curr < buf_end)
    {
      word_begin = curr;
      uchr = eh_decode_char__UTF8 (&curr, buf_end);
      prop = unichar_getprops (uchr);
      if (prop & UCP_ALPHA)
	{
	  check_buf[0] = uchr;
	  word_length = 1;
	  for(;;)
	    {
	      word_end = curr;
	      uchr = eh_decode_char__UTF8 (&curr, buf_end);
	      if (uchr < 0)
		{
		  if ((UNICHAR_NO_DATA == uchr) || (UNICHAR_BAD_ENCODING == uchr))
		    return uchr;
		  if (UNICHAR_EOD == uchr)
		    break;
		}
	      prop = unichar_getprops (uchr);
	      if (!(prop & UCP_ALPHA))
		break;
	      if (WORD_MAX_CHARS > word_length)
		check_buf[word_length] = uchr;
	      word_length++;
	    }
	  if (WORD_MAX_CHARS < word_length)
	    goto done_word;
	  if (NULL!=check && 0 == check (check_buf, word_length))
	    goto done_word;
	  if (NULL != patch)
	    {
	      if (0 == patch (check_buf, word_length, patch_buf, &arg_length))
		goto done_word;
	      arg_begin = patch_buf;
	    }
	  else
	    {
	      callback ((utf8char *) word_begin, word_end-word_begin, userdata);
	      goto done_word;
	    }
	  word_end = eh_encode_buffer__UTF8 (arg_begin, arg_begin+arg_length, word_buf, word_buf+BUFSIZEOF__UTF8_WORD);
	  if (NULL != word_end)
	    {
	      callback ((utf8char *)(word_buf), word_end-word_buf, userdata);
	      goto done_word;
	    }
	  if (hugeword_buf_size<(word_length*MAX_UTF8_CHAR))
	    {
	      if (hugeword_buf_size)
		dk_free (hugeword_buf, hugeword_buf_size);
	      hugeword_buf_size = word_length*MAX_UTF8_CHAR;
	      hugeword_buf = (char *) dk_alloc (hugeword_buf_size);
	    }
	  word_end = eh_encode_buffer__UTF8 (arg_begin, arg_begin+arg_length, hugeword_buf, hugeword_buf+hugeword_buf_size);
	  callback ((utf8char *)(hugeword_buf), word_end-hugeword_buf, userdata);
done_word:
	  if (prop & UCP_IDEO)
	    goto proc_ideo;
	  continue;
	}
      if (prop & UCP_IDEO)
	{
proc_ideo:
	  check_buf[0] = uchr;
	  if (NULL!=check && 0 == check (check_buf, 1))
	    continue;
	  if (NULL != patch)
	    {
	      if (0 == patch (check_buf, 1, patch_buf, &arg_length))
		continue;
	      arg_begin = patch_buf;
	    }
	  else
	    {
	      callback ((utf8char *) word_begin, curr-word_begin, userdata);
	      continue;
	    }
	  word_end = eh_encode_buffer__UTF8 (arg_begin, arg_begin+arg_length, word_buf, word_buf+BUFSIZEOF__UTF8_WORD);
	  callback ((utf8char *)(word_buf), word_end-word_buf, userdata);
	  continue;
	}
      if ((uchr < 0) && ((UNICHAR_NO_DATA == uchr) || (UNICHAR_BAD_ENCODING == uchr)))
	goto cleanup; /* see below */
    }
  uchr = 0;
cleanup:
  if (hugeword_buf_size)
    dk_free (hugeword_buf, hugeword_buf_size);
  return uchr;
}
void LH_ITERATE_PATCHED_WORDS_NAME(const unichar *buf, size_t bufsize, lh_word_check_t *check, lh_word_patch_t *patch, lh_word_callback_t *callback, void *userdata)
{
  size_t pos = 0;
  size_t word_start;
  size_t word_length;
  unichar patch_buf[WORD_MAX_CHARS];
  const unichar *arg_begin;
  size_t arg_length;
  utf8char word_buf[BUFSIZEOF__UTF8_WORD];
  utf8char *hugeword_buf = NULL;
  size_t hugeword_buf_size = 0;
  utf8char *word_end;
  int prop;
#ifdef LH_ITERATOR_DEBUG
  int wordctr = 0, wordcount = LH_COUNT_WORDS_NAME (buf, bufsize, check);
#define wordctr_INC1 wordctr++
#else
#define wordctr_INC1
#endif
  while (pos < bufsize)
    {
      prop = UNICHAR_GETPROPS_EXPN(buf,bufsize,pos);
      if (prop & UCP_ALPHA)
	{
	  word_start = pos;
	  do pos++; while ((pos < bufsize) && (UNICHAR_GETPROPS_EXPN(buf,bufsize,pos) & UCP_ALPHA));
	  word_length = pos - word_start;
	  if (WORD_MAX_CHARS < word_length)
	    continue;
	  if (NULL!=check && 0 == check(buf+word_start, word_length))
	    {
	      DBG_PRINTF_NOISE_WORD(word_start,word_length);
	      continue;
	    }
	  if (NULL != patch)
	    { /* word should be patched */
	      if (0 == patch (buf+word_start, word_length, patch_buf, &arg_length))
		{
		  DBG_PRINTF_PATCH_FAILED(word_start,word_length);
		  continue;
		}
	      arg_begin = patch_buf;
	    }
	  else
	    { /* argument should be taken right from \c buf */
	      arg_begin = buf+word_start;
	      arg_length = word_length;
	    }
	  word_end = (utf8char *)eh_encode_buffer__UTF8 (arg_begin, arg_begin+arg_length, (char *)(word_buf), (char *)(word_buf+BUFSIZEOF__UTF8_WORD));
	  if (NULL != word_end)
	    {
	      callback (word_buf, word_end-word_buf, userdata);
              wordctr_INC1;
	      continue;
	    }
	  if (hugeword_buf_size<(word_length*MAX_UTF8_CHAR))
	    { /* overflow danger detected */
	      if (hugeword_buf_size)
		dk_free (hugeword_buf, hugeword_buf_size);
	      hugeword_buf_size = word_length*MAX_UTF8_CHAR;
	      hugeword_buf = (utf8char *) dk_alloc (hugeword_buf_size);
	    }
	  word_end = (utf8char *)eh_encode_buffer__UTF8 (arg_begin, arg_begin+arg_length, (char *)(hugeword_buf), (char *)(hugeword_buf+hugeword_buf_size));
	  callback (hugeword_buf, word_end-hugeword_buf, userdata);
          wordctr_INC1;
	  continue;
	}
      if (prop & UCP_IDEO)
	{
	  word_start = pos;
	  pos++;
	  word_length = pos - word_start;
	  if (NULL!=check && 0 == check(buf+word_start, word_length))
	    {
	      DBG_PRINTF_NOISE_IDEO(word_start,word_length);
	      continue;
	    }
	  if (NULL != patch)
	    { /* word should be patched */
	      if (0 == patch (buf+word_start, word_length, patch_buf, &arg_length))
		{
		  DBG_PRINTF_IDEO_PATCH_FAILED(word_start,word_length);
		  continue;
		}
	      arg_begin = patch_buf;
	    }
	  else
	    { /* argument should be taken right from \c buf */
	      arg_begin = buf+word_start;
	      arg_length = word_length;
	    }
	  word_end = (utf8char *)eh_encode_buffer__UTF8 (arg_begin, arg_begin+arg_length, (char *)(word_buf), (char *)(word_buf+BUFSIZEOF__UTF8_WORD));
	  callback (word_buf, word_end-word_buf, userdata);
          wordctr_INC1;
	  continue;
	}
      pos++;
    }
  if (hugeword_buf_size)
    dk_free (hugeword_buf, hugeword_buf_size);
#ifdef LH_ITERATOR_DEBUG
  if (wordctr != wordcount)
    GPF_T;
#endif
}