Пример #1
0
void setup_macro(struct macro_head *h, int arity, struct pnode *parms)
{
  if (enforce_arity(arity, list_length(h->parms))) {
    /* push table for the marco parms */
    state.stTopDefines = push_symbol_table(state.stTopDefines, 
                                        state.case_insensitive);

    /* Now add the macro's declared parameter list to the new 
       defines table. */
    if (arity > 0) {
      struct pnode *pFrom, *pFromH;
      struct pnode *pTo, *pToH;
      struct symbol *sym;

      pTo = parms;

      for (pFrom = h->parms; pFrom; pFrom = TAIL(pFrom)) {
	pToH = HEAD(pTo);
	pFromH = HEAD(pFrom);
	assert(pFromH->tag == symbol);
 
        arg_index = 0;
        arg_buffer[0] = '\0';
        node_to_string(pToH);
        sym = add_symbol(state.stTopDefines, pFromH->value.symbol);	
        annotate_symbol(sym, strdup(arg_buffer));
        pTo = TAIL(pTo);
      }
    }

    state.next_state = state_macro;  
    state.next_buffer.macro = h;
    state.lst.line.linetype = none;
  }
}
// expand partial ref (it is ensured to be leaf by toposort), and eliminate nil rules
static void _expand_lex_def(struct ContextMap* context_map, Val name) {
  Val curr;
  bool found = ContextMap.find(context_map, name, &curr);
  assert(found);
  Val res = VAL_NIL;

  for (; curr != VAL_NIL; curr = TAIL(curr)) {
    if (IS_A(HEAD(curr), "RefPartialContext")) {
      Val ref_name = AT(HEAD(curr), 0);
      Val child_nodes;
      bool found = ContextMap.find(context_map, ref_name, &child_nodes);
      if (!found) {
        COMPILE_ERROR("partial context not found: %.*s", (int)nb_string_byte_size(ref_name), nb_string_ptr(ref_name));
      }
      for (Val child_curr = child_nodes; child_curr != VAL_NIL; child_curr = TAIL(child_curr)) {
        if (child_curr != VAL_NIL) {
          res = nb_cons_new(child_curr, res);
        }
      }
    }
  }

  // yes it allocs more, but necessary to keep the order consistent
  ContextMap.insert(context_map, name, nb_cons_reverse(res));
}
void enqueue(queue q, int n)
{
	node nd = malloc(sizeof(node_t));
	nd->val = n;
	if (!HEAD(q)) HEAD(q) = nd;
	nd->prev = TAIL(q);
	if (nd->prev) nd->prev->next = nd;
	TAIL(q) = nd;
	nd->next = 0;
}
int dequeue(queue q, int *val)
{
	node tmp = HEAD(q);
	if (!tmp) return 0;
	*val = tmp->val;

	HEAD(q) = tmp->next;
	if (TAIL(q) == tmp) TAIL(q) = 0;
	free(tmp);

	return 1;
}
Пример #5
0
void enqueue(queue q, ThrdCtlBlk n)
{
        node nd = malloc(sizeof(node_t));
        nd->block = n;
        if (!HEAD(q)){
          HEAD(q) = nd;
        }
        nd->prev = TAIL(q);
        if (nd->prev){
          nd->prev->next = nd;
        }
        TAIL(q) = nd;
        nd->next = 0;
}
Пример #6
0
void setup_macro(struct macro_head *h, int arity, struct pnode *parms)
{
  if (enforce_arity(arity, list_length(h->parms))) {
    /* push table for the marco parms */
    state.stTopDefines = push_symbol_table(state.stTopDefines, 
                                        state.case_insensitive);

    /* Now add the macro's declared parameter list to the new 
       defines table. */
    if (arity > 0) {
      struct pnode *pFrom, *pFromH;
      struct pnode *pTo, *pToH;
      struct symbol *sym;
      char buffer[BUFSIZ];

      pTo = parms;

      for (pFrom = h->parms; pFrom; pFrom = TAIL(pFrom)) {
	pToH = HEAD(pTo);
	pFromH = HEAD(pFrom);
	assert(pFromH->tag == symbol);
 
        sym = add_symbol(state.stTopDefines, pFromH->value.symbol);	

        /* must convert the parm to a plain string, this will allow
           subsitutions of labels and strings */
        if (pToH->tag == symbol) {
          annotate_symbol(sym, strdup(pToH->value.symbol));
        } else if (pToH->tag == string) {
          sprintf(buffer, "\"%s\"", pToH->value.string);
          annotate_symbol(sym, strdup(buffer));
        } else {
          int value = maybe_evaluate(pToH);

	  if (value < 0)
	    sprintf(buffer, "-%#x", -value);
          else
	    sprintf(buffer, "%#x", value);	  
	  annotate_symbol(sym, strdup(buffer));
        }
    
        pTo = TAIL(pTo);
      }
    }

    state.next_state = _macro;  
    state.next_buffer.macro = h;
    state.lst.line.linetype = none;
  }
}
Пример #7
0
int dequeue(queue q, ThrdCtlBlk *val)
{
        node tmp = HEAD(q);
        if (!tmp){
          return 0;
        }
        *val = tmp->block;

        HEAD(q) = tmp->next;
        if (TAIL(q) == tmp){
          TAIL(q) = 0;
        }
        free(tmp);

        return 1;
}
Пример #8
0
static int print_string(FILE* fp, const ETERM* ep)
{
    int ch_written = 0; /* counter of written chars */
  
    putc('"', fp);
    ch_written++;
    while (ERL_IS_CONS(ep)) {
	int c = ERL_INT_VALUE(HEAD(ep));

	if (c >= ' ') {
	    putc(c, fp);
	    ch_written++;
	}
	else {
	    switch (c) {
	    case '\n': fputs("\\n", fp); ch_written += 2; break;
	    case '\r': fputs("\\r", fp); ch_written += 2; break;
	    case '\t': fputs("\\t", fp); ch_written += 2; break;
	    case '\v': fputs("\\v", fp); ch_written += 2; break;
	    case '\b': fputs("\\b", fp); ch_written += 2; break;
	    case '\f': fputs("\\f", fp); ch_written += 2; break;
		break;
	    default:
		ch_written += fprintf(fp, "\\%o", c);
		break;
	    }
	}
	ep = TAIL(ep);
    }
    putc('"', fp);
    ch_written++;
    return ch_written;
}
Пример #9
0
static int is_printable_list(const ETERM* term)
{
    while (ERL_TYPE(term) == ERL_LIST) {
	ETERM* head = HEAD(term);

	if (!ERL_IS_BYTE(head)) {
	    return 0;
	}
	if (ERL_INT_VALUE(head) < ' ') {
	    switch (ERL_INT_VALUE(head)) {
	    case '\n':
	    case '\r':
	    case '\t':
	    case '\v':
	    case '\b':
	    case '\f':
		break;
	    default:
		return 0;
	    }
	}
	term = TAIL(term);
    }

    return ERL_IS_EMPTY_LIST(term);
}
Пример #10
0
static void iolist_to_buf(const ETERM* term, char** bufp)
{
    char* dest = *bufp;

    while (ERL_IS_CONS(term)) {
	ETERM* obj = HEAD(term);

	if (ERL_IS_BYTE(obj)) {
	    *dest++ = ERL_INT_VALUE(obj);
	} else if (ERL_IS_CONS(obj)) {
	    iolist_to_buf(obj, &dest);
	} else if (ERL_IS_BINARY(obj)) {
	    memcpy(dest, ERL_BIN_PTR(obj), ERL_BIN_SIZE(obj));
	    dest += ERL_BIN_SIZE(obj);
	} else {
	    /*
	     * Types have been checked by caller.
	     */
	  if (!ERL_IS_EMPTY_LIST(obj)) return;
	  /* ASSERT(ERL_IS_EMPTY_LIST(obj)); */
	}
	term = TAIL(term);
    }
    if (ERL_IS_BINARY(term)) {
	memcpy(dest, ERL_BIN_PTR(term), ERL_BIN_SIZE(term));
	dest += ERL_BIN_SIZE(term);
    } else {
	/*
	 * Types have been checked by caller.
	 */
      if (!ERL_IS_EMPTY_LIST(term)) return;
      /* ASSERT(ERL_IS_EMPTY_LIST(term));*/
    }
    *bufp = dest;
}
Пример #11
0
ETERM *erl_mk_estring(const char *s, int len)
{
    ETERM *ep;
    int i;

    if ((!s) || (len < 0)) return NULL;

    /*
     * ASSERT(s != NULL);
     * ASSERT(len >= 0);
     */

    ep = erl_mk_empty_list();
    for (i = len-1; i >= 0; i--) {
	ETERM* integer;
	ETERM* cons;

	integer = erl_alloc_eterm(ERL_INTEGER);
	ERL_COUNT(integer) = 1;
	ERL_INT_VALUE(integer) = (unsigned char)s[i];

	cons = erl_alloc_eterm(ERL_LIST);
	ERL_COUNT(cons) = 1;
	HEAD(cons) = integer;
	TAIL(cons) = ep;
	ep = cons;
    }
    return ep;
}
Пример #12
0
int erl_iolist_length (const ETERM* term)
{
    int len = 0;

    while (ERL_IS_CONS(term)) {
	ETERM* obj = HEAD(term);

	if (ERL_IS_BYTE(obj)) {
	    len++;
	} else if (ERL_IS_CONS(obj)) {
	    int i;
	    if ((i = erl_iolist_length(obj)) < 0)
		return i;
	    len += i;
	} else if (ERL_IS_BINARY(obj)) {
	    len += ERL_BIN_SIZE(obj);
	} else if (!ERL_IS_EMPTY_LIST(obj)) {
	    return(-1);
	}
	term = TAIL(term);
    }
    if (ERL_IS_EMPTY_LIST(term))
	return len;
    else if (ERL_IS_BINARY(term))
	return len + ERL_BIN_SIZE(term);
    else
	return -1;
}
Пример #13
0
static void
write_statements(tree *statements)
{
  tree *list;
  tree *statement;

  list = statements;
  assert(list->tag == node_list);
  while(list) {
    statement = HEAD(list);
    switch(statement->tag) {
    case node_call:
      write_call(statement);
      break;
    case node_cond:
      write_cond(statement);  
      break;
    case node_loop:
      write_loop(statement);
      break; 
    default:
      write_expression(statement);
    }
    list = TAIL(list);
  }

}
Пример #14
0
int extract(queue q, Tid val, ThrdCtlBlk *retval)
{
        if(empty(q)) {
          return 0;
        }

        node tmp = HEAD(q);
        while(!tmp)  //!(tmp->block == val) && tmp->next != 0)
        {
          ThrdCtlBlk tmpBlock = tmp->block;
          Tid tidval = tmpBlock.tid;
          if(tidval == val) {
            break;
          }

          tmp = tmp->next;
        }

        if(tmp)
        {
          if(tmp == HEAD(q)) {
           dequeue(q,retval);
           return 1;
          }
          if (TAIL(q) == tmp) {
            TAIL(q) = 0;
            node p = tmp->prev;
            p->next = TAIL(q);
            *retval = tmp->block;
            return 1;
          }
          else {
            node p = tmp->prev;
            node n = tmp->next;
            p->next = n;
            n->prev = p;
            retval = &tmp->block;
            return 1;
          }
        }
        else
        {
          return 0;
        }
}
Пример #15
0
static
int list_length(tree *L)
{
  if (L == NULL) {
    return 0;
  } else {
    return 1 + list_length(TAIL(L));
  }
}
Пример #16
0
int list_length(struct pnode *L)
{
  struct pnode *p = L;
  int n = 0;

  while (p && list == p->tag) {
    ++n;
    p = TAIL(p);
  }

  return (NULL != p) ? n + 1: n;
}
Пример #17
0
/* 
 * Extract the TAIL of a LIST. Bump the reference
 * counter on the tail object.
 */
ETERM *erl_tl (const ETERM *ep)
{
    ETERM *tl;

    if (!ep) return NULL;
    /* ASSERT(ep != NULL); */

    if (ERL_TYPE(ep) != ERL_LIST) {
	return (ETERM *) NULL; 
    }

    tl = TAIL(ep);
    ERL_COUNT(tl)++;
    return tl;
}
Пример #18
0
void 
cfree (void *ptr)
{
  struct header *q = (struct header *)ptr-1;
  int qsize = q->size;
  char *qtail = TAIL(q);
  
  struct header *prev = freeList;
  struct header *p = prev->next;
  
  while (p && p->next<q){
    prev = p;
    p = p->next;
  }
  char *prevtail = TAIL(prev);
  if (prevtail==(void *)q && qtail == (void *)p){
    prev->size += (q->size+p->size);
    prev->next = p->next;
    return;
  }
  else if (prevtail == (void *)q){
    prev->size += q->size;
    return;
  }
  else if (qtail == (void *)p){
    q->size += p->size;
    q->next = p;
    prev->next = q;
    return;
  }
  else {
    q->next = p;
    prev->next = q;
    return;
  }
}
Пример #19
0
/*
 * Return the LENGTH of a LIST.
 * At failure -1 is returned (this include non-proper lists like [a|b]).
 */
int erl_length(const ETERM *ep)
{
    int n = 0;

    if (!ep) return -1;
    /* ASSERT(ep != NULL); */

    while (ERL_TYPE(ep) == ERL_LIST) {
      n++;
      ep = TAIL(ep);
    }

    if (!ERL_IS_EMPTY_LIST(ep)) return -1;

    return n;
}
Пример #20
0
static void
extern_args(char *main_name, tree *list)
{
  tree *decl;
  tree *symbol;

  while (list) {
    decl = HEAD(list);
    assert(decl->tag == node_decl);
    symbol = decl->value.decl.expr;
    assert(symbol->tag == node_symbol);
    extern_name(main_name, symbol->value.symbol, symbol);
    list = TAIL(list);
  }

}
Пример #21
0
/* Insert a new element at the end; chan->lock must be held.
 * Returns 0 if data has been written or if data may be written
 * if 'data' is NULL. */
static int
channel_write(sdb_channel_t *chan, const void *data)
{
	assert(chan);

	if (chan->full || chan->shutdown)
		return -1;
	else if (! data)
		return 0;

	memcpy(TAIL(chan), data, chan->elem_size);
	chan->tail = NEXT_WRITE(chan);

	chan->full = chan->tail == chan->head;
	pthread_cond_broadcast(&chan->cond);
	return 0;
} /* channel_write */
Пример #22
0
static void
write_declarations(void)
{
  entity *entity_list = NULL;
  tree *current = NULL;
  int first_time = 1;
  tree *list;  
  tree *symbol;

  entity_list = state.list;

  while (entity_list != NULL) {
    current = entity_list->node;
    if ((current->tag == node_decl) && 
        (current->value.decl.storage != EXTERN_STORAGE)) {
      if ((current->value.decl.type == CONST_TYPE) &&
          (current->value.decl.storage != 0)) {
        gp_error("constants can't be public or volatile");
      } 
      /* FIXME: only bytes are supported so far */
      assert(current->value.decl.size == BYTE_SIZE);
      if (first_time) {
        fprintf(state.output.f, "; declarations \n");
        fprintf(state.output.f, "  udata\n");
        first_time = 0;      
      }
      for (list = current->value.decl.expr; list; list = TAIL(list)) {
        symbol = HEAD(list);
        assert(symbol->tag == node_symbol);
        if (current->value.decl.type == VAR_TYPE) {
          fprintf(state.output.f, "%s res 1\n", symbol->value.symbol);
          if (current->value.decl.storage == PUBLIC_STORAGE)
            fprintf(state.output.f, "  global %s\n", symbol->value.symbol);
        }
        add_global(symbol->value.symbol, symbol->value.symbol, current);
      }
    }
    entity_list = entity_list->next;
  }

  if (!first_time)
    fprintf(state.output.f, "\n");

}
Пример #23
0
/* 
 * Return the CONTENT of a VARIABLE with NAME.
 * If the content is non-nil then bump its
 * reference counter.
 */
ETERM *erl_var_content (const ETERM *ep, const char *name)
{
  int i;
  ETERM *vp;

  if ((!ep) || (!name)) return NULL;
    
  /*   ASSERT(ep != NULL); */

  switch(ERL_TYPE(ep)) 
    {
    case ERL_VARIABLE:
	if (strcmp(ERL_VAR_NAME(ep), name) == 0) {
	    if ((vp = ERL_VAR_VALUE(ep)) != NULL) {
		ERL_COUNT(vp)++;
		return vp;
	    }
	}
	break;

    case ERL_LIST:
      while (ep && (ERL_TYPE(ep) != ERL_EMPTY_LIST)) {
	if ((vp = erl_var_content(HEAD(ep), name))) return vp;
	ep = TAIL(ep);
      }
      break;

    case ERL_TUPLE:
      for (i=0; i < ERL_TUPLE_SIZE(ep); i++) 
	  if ((vp = erl_var_content(ERL_TUPLE_ELEMENT(ep, i), name)))
	  {
	      return vp;
	  }
      break;
    
    default:
      /* variables can't occur in other types */
      break;
    }
    
  /* nothing found ! */
  return NULL;
}
Пример #24
0
/*
 * Construct a new list by CONS'ing a HEAD on
 * to the TAIL. Bump the reference counter on
 * the head and tail object. Note that we allow
 * non-well formed lists to be created.
 */
ETERM *erl_cons(ETERM *hd, ETERM *tl)
{
    ETERM *ep;

    if ((!hd) || (!tl)) return NULL;

    /*
     * ASSERT(hd != NULL);
     * ASSERT(tl != NULL);
     */

    ep = erl_alloc_eterm(ERL_LIST);
    ERL_COUNT(ep) = 1;
    HEAD(ep) = hd;
    TAIL(ep) = tl;
    ERL_COUNT(hd)++;
    ERL_COUNT(tl)++;
    return ep;
}
Пример #25
0
void *
cmalloc (int bytes)
{
  if (bytes<0)
    die("bad mem length");

  if (!memChunk){
    // Use "malloc" instead of "brk" makes this 
    // allocator portable.
    memChunk = malloc (MEM_SIZE);
    if (!memChunk)
      die ("out of memory");

    freeList = &theHeader;

    assert ((void *)freeList < memChunk);

    freeList->next = (struct header *)memChunk;
    freeList = &theHeader;
    freeList->next->size = MEM_SIZE;
    freeList->next->next = 0;
  }
  // first time match
  struct header *prev = freeList;
  struct header *p = prev->next;
  while (p && p->size-HEADER_SIZE < bytes){
    prev = p;
    p = p->next;
  }
  if (!p)
    die ("no memory chunk found");
  
  if (p->size-HEADER_SIZE == bytes){
    prev->next = p->next;
    return ++p;
  }
  // p->size-HEADER_SIZE > bytes
  struct header *q = (struct header *)(TAIL(p)-bytes-HEADER_SIZE);
  q->next = 0;
  q->size = bytes+HEADER_SIZE;
  p->size -= (bytes+HEADER_SIZE);
  return ++q;
}
Пример #26
0
static void
write_decl(tree *decl, char *name)
{
  tree *list;  
  tree *symbol;
  char alias[BUFSIZ];

  assert(decl->tag == node_decl);
  list = decl->value.decl.expr;
  assert(list->tag == node_list);

  for (; list; list = TAIL(list)) {
    symbol = HEAD(list);
    assert(symbol->tag == node_symbol);
    sprintf(alias, "%s_%s", name, symbol->value.symbol);
    add_global(symbol->value.symbol, alias, symbol);
    if (decl->value.decl.type == VAR_TYPE) {
      fprintf(state.output.f, "%s res 1\n", alias);
    }
  }

}
Пример #27
0
/* Links the named object files for dynamic loading, reads it in, and returns
   a "foreign_file" object which allows access to its symbols.  If
   names is a non-empty list (of byte-strings), then make ld "undefine"
   these names so that they will show up in the linked version. */
obj_t load_c_file(obj_t /* list */ c_files, obj_t /* list */ names)
{
    int i;
    obj_t retval = obj_False;
    struct shared_file *ret;
    shl_t handle;

    retval = alloc(obj_SharedFileClass,
                   sizeof(struct shared_file)
                     + ((length(c_files) - 1) * sizeof(shl_t)));
    ret = obj_ptr(struct shared_file *, retval);
    ret->file_count = length(c_files);
    for (i = 0; c_files != obj_Nil; i++, c_files = TAIL(c_files)) {
        handle = shl_load(string_chars(HEAD(c_files)));
        if (handle == NULL) {
            error("Can't load shared library %s.", HEAD(c_files));
        };
        ret->handles[i] = handle;
        ret->file_name = HEAD(c_files);
    }
    return retval;
}
Пример #28
0
static inline isc_boolean_t
task_shutdown(isc__task_t *task) {
	isc_boolean_t was_idle = ISC_FALSE;
	isc_event_t *event, *prev;

	/*
	 * Caller must be holding the task's lock.
	 */

	XTRACE("task_shutdown");

	if (! TASK_SHUTTINGDOWN(task)) {
		XTRACE(isc_msgcat_get(isc_msgcat, ISC_MSGSET_GENERAL,
				      ISC_MSG_SHUTTINGDOWN, "shutting down"));
		task->flags |= TASK_F_SHUTTINGDOWN;
		if (task->state == task_state_idle) {
			INSIST(EMPTY(task->events));
			task->state = task_state_ready;
			was_idle = ISC_TRUE;
		}
		INSIST(task->state == task_state_ready ||
		       task->state == task_state_running);

		/*
		 * Note that we post shutdown events LIFO.
		 */
		for (event = TAIL(task->on_shutdown);
		     event != NULL;
		     event = prev) {
			prev = PREV(event, ev_link);
			DEQUEUE(task->on_shutdown, event, ev_link);
			ENQUEUE(task->events, event, ev_link);
		}
	}

	return (was_idle);
}
Пример #29
0
/**
 * Change setting 'name' to value specified by attribute 'attr_name' in LDAP
 * entry. Setting is un-set if specified value is missing in LDAP entry.
 *
 * @warning Multi-value attributes are no supported.
 *
 * @retval ISC_R_SUCCESS  Setting was changed (set or unset).
 * @retval ISC_R_IGNORE   Setting wasn't changed because value in settings set
 *                        and LDAP entry was same.
 * @retval ISC_R_NOTFOUND Required setting was not found in given set.
 * @retval Others         Memory allocation or conversion errors.
 */
isc_result_t
setting_update_from_ldap_entry(const char *name, settings_set_t *set,
			       const char *attr_name, ldap_entry_t *entry) {
	isc_result_t result;
	setting_t *setting = NULL;
	ldap_valuelist_t values;

	CHECK(setting_find(name, set, ISC_FALSE, ISC_FALSE, &setting));
	result = ldap_entry_getvalues(entry, attr_name, &values);
	if (result == ISC_R_NOTFOUND || HEAD(values) == NULL) {
		CHECK(setting_unset(name, set));
		log_debug(2, "setting '%s' (%s) was deleted in object %s",
			  name, attr_name, ldap_entry_logname(entry));
		return ISC_R_SUCCESS;

	} else if (result != ISC_R_SUCCESS) {
		goto cleanup;
	}

	if (HEAD(values) != TAIL(values)) {
		log_bug("multi-value attributes are not supported: attribute "
			"'%s' in %s", attr_name,
			ldap_entry_logname(entry));
		return ISC_R_NOTIMPLEMENTED;
	}

	CHECK(setting_set(name, set, HEAD(values)->value));
	log_debug(2, "setting '%s' (%s) was changed to '%s' in %s", name,
		  attr_name, HEAD(values)->value, ldap_entry_logname(entry));

cleanup:
	if (result == ISC_R_NOTFOUND)
		log_bug("setting '%s' was not found in settings set '%s'",
			name, set->name);
	return result;
}
Пример #30
0
int erl_print_term(FILE *fp, const ETERM *ep)
{
    int j,i,doquote;
    int ch_written = 0; /* counter of written chars */

    if ((!fp) || (!ep)) return 0;
    /* ASSERT(ep != NULL); */

    j = i = doquote = 0;
    switch(ERL_TYPE(ep)) 
    {
    case ERL_ATOM: {
	char* adata = ERL_ATOM_PTR(ep);
	/* FIXME: what if some weird locale is in use? */
	if (!islower(adata[0]))
	    doquote = 1;

	for (i = 0; !doquote && i < ERL_ATOM_SIZE(ep); i++) 
	{
	    doquote = !(isalnum(adata[i]) || (adata[i] == '_'));
	}

	if (doquote) {
	    putc('\'', fp);
	    ch_written++; 
	}
	fputs(adata, fp);
	ch_written += ERL_ATOM_SIZE(ep);	
	if (doquote) {
	    putc('\'', fp);
	    ch_written++;
	}
	break;
    }
    case ERL_VARIABLE:
	if (!isupper((int)ERL_VAR_NAME(ep)[0])) {
	    doquote = 1;
	    putc('\'', fp);
	    ch_written++;
	}
	
	fputs(ERL_VAR_NAME(ep), fp);
	ch_written += ERL_VAR_LEN(ep);
	
	if (doquote) {
	    putc('\'', fp);
	    ch_written++;
	}
	break;

    case ERL_PID:
	ch_written += fprintf(fp, "<%s.%d.%d>", 
			    ERL_PID_NODE(ep), 
			    ERL_PID_NUMBER(ep), ERL_PID_SERIAL(ep));
      break;
    case ERL_PORT:
      ch_written += fprintf(fp, "#Port");
      break;
    case ERL_REF:
      ch_written += fprintf(fp, "#Ref");
      break;
    case ERL_EMPTY_LIST:
      ch_written += fprintf(fp, "[]");
      break;
    case ERL_LIST: 
	if (is_printable_list(ep)) {
	    ch_written += print_string(fp, ep);
	} else {
	    putc('[', fp);
	    ch_written++;
	    while (ERL_IS_CONS(ep)) {
		ch_written += erl_print_term(fp, HEAD(ep));
		ep = TAIL(ep);
		if (ERL_IS_CONS(ep)) {
		    putc(',', fp);
		    ch_written++;
		}
	    }
	    if (!ERL_IS_EMPTY_LIST(ep)) {
		putc('|', fp);
		ch_written++;
		ch_written += erl_print_term(fp, ep);
	    }
	    putc(']', fp);
	    ch_written++;
	}
	break;
    case ERL_TUPLE:
      putc('{', fp);
      ch_written++;
      for (i=0; i < ERL_TUPLE_SIZE(ep); i++) {
	ch_written += erl_print_term(fp, ERL_TUPLE_ELEMENT(ep, j++) );
	if (i != ERL_TUPLE_SIZE(ep)-1) {
	  putc(',', fp);
	  ch_written++;
	}
      }
      putc('}', fp);
      ch_written++;
      break;
    case ERL_BINARY: {
	int sz = (ERL_BIN_SIZE(ep) > 20) ? 20 : ERL_BIN_SIZE(ep);
	unsigned char *ptr = ERL_BIN_PTR(ep);
	ch_written += fprintf(fp, "#Bin<");
	for (i = 0; i < sz; i++) { 
	    putc(ptr[i], fp); ch_written++;
	}
	if (sz == 20) ch_written += fprintf(fp, "(%d)....>", ERL_BIN_SIZE(ep)-20);
	else ch_written += fprintf(fp, ">");
	break;
      }
    case ERL_INTEGER:
    case ERL_SMALL_BIG:
      ch_written += fprintf(fp, "%d", ERL_INT_VALUE(ep));
      break;
    case ERL_U_INTEGER:
    case ERL_U_SMALL_BIG:
      ch_written += fprintf(fp, "%d", ERL_INT_UVALUE(ep));
      break;
    case ERL_LONGLONG:
    case ERL_U_LONGLONG:
      ch_written += fprintf(fp, "%lld", ERL_LL_UVALUE(ep));
      break;
    case ERL_FLOAT:
      ch_written += fprintf(fp, "%f", ERL_FLOAT_VALUE(ep));
      break;
    case ERL_FUNCTION:
      ch_written += fprintf(fp, "#Fun<");
      ch_written += erl_print_term(fp, ERL_FUN_MODULE(ep));
      putc('.', fp);
      ch_written++;
      ch_written += erl_print_term(fp, ERL_FUN_INDEX(ep));
      putc('.', fp);
      ch_written++;
      ch_written += erl_print_term(fp, ERL_FUN_UNIQ(ep));
      putc('>', fp);
      ch_written++;
      break;
    default:
      ch_written = -10000;
      erl_err_msg("<ERROR> erl_print_term: Bad type of term !");
    }
  return ch_written;
}