/*
** patdef.c for  in 
** 
** Made by 
** Login   <vianney@epita.fr>
** 
** Started on  Wed Sep  1 06:40:27 1999 
** Last update Thu Oct 28 20:19:22 1999 
*/
#include "pat.h"

/* is a t_tmpl_do_proc.
   It transforms %i% to the value of i.
   See also pat_get_itmpl_generic(3).
   Returns 0 if OK. Might return various errors. */
t_status			itmpl_format_do(bs,var,i)
t_bridled_str			*bs;
char				*var;
int				i;
{
  int				varlen;
  long				signedvalue;
  t_status			status;

  varlen = strlen(var);
  if (varlen == 0)
    return (str_cat_char(bs->str,bs->max_len,'%'));
  else
    {
      if (!strcmp(var,"i"))
	{
	  return (long_to_str((signed long)i,
			      10,
			      bs->str,
			      bs->max_len));
	}
    }
  return (0);
}

/* formats an "itmpl" to a "tmpl".
   It is used mostly to allow indexation of pats.
   Returns 0 if OK. Might return various errors. */
t_status			itmpl_format(i,itmpl_str,str,max_len)
int				i;
char				*itmpl_str;
char				*str;
int				max_len;
{
  return (tmpl_str_to_str(itmpl_str,
			  (t_tmpl_do_proc)itmpl_format_do,
			  (VOID_PTR)i,
			  str,
			  max_len));
}

t_status			get_field_to_str(buf,
						 len,
						 field,
						 str,
						 max_len)
char				*buf;
int				len;
t_field				*field; /* Field specification */
char				*str;
int				max_len;
{
  t_status			status;
  char				*buf2;
  int				len2;

  if (field->offset >= len)
    return (ERR_PAT_TRUNC_FIELD);
  buf2 = buf + field->offset;
  len2 = len - field->offset;
  if (!field->pat->extract_proc)
    return (ERR_PAT_NO_METHOD_EXTRACT);
  if ((status = field->pat->extract_proc(field->data,
					 buf2,
					 len2,
					 str,
					 max_len)) != 0)
    return (status);
  return (0);
}

t_status			set_field_from_str(buf,
						   len,
						   field,
						   str)
char				*buf;
int				len;
t_field				*field; /* Field specification */
char				*str; 
{
  t_status			status;
  char				*buf2;
  int				len2;

  if (field->offset >= len)
    return (ERR_PAT_TRUNC_FIELD);
  buf2 = buf + field->offset;
  len2 = len - field->offset;
  if (!field->pat->insert_proc)
    return (ERR_PAT_NO_METHOD_INSERT);
  if ((status = field->pat->insert_proc(field->data,
					buf2,
					len2,
					str)) != 0)
    return (status);
  return (0);
}

t_status		pat_name_generic(optional_id,str,max_len,chan,name)
t_id			*optional_id;	/* Might be NULL in such case
						   name won't be indexed and
					   output will look like "ip" instead
					   of "ip[something]" */
char			*str;
int			max_len;
VOID_PTR		chan;		/* Channel */
char			*name;		/* Base name of pat, e.g "ip" */
{
  if (optional_id)
    {
      t_hash_elt	*he;
      int		i;
      t_status		status;
      
      if (he = id_get(optional_id,
		      chan))
	i = (int)(he->value);
      else
        i = 0;
      if ((status = str_cat_fmt_va(str,
				   max_len,
				   "%s[%d]",
				   name,
				   i)) != 0)
        return (status);
      if ((status = id_override(optional_id,
				chan,
				(VOID_PTR)(++i))) != 0)
        return (status);
      return (0);
   }
   else
     return (str_cat_str(str,
			 max_len,
			 name));
}

t_status		pat_get_field_generic(optional_id,
					      buf,
					      len,
					      field,
					      str,
					      max_len,
					      fields) 
t_id			*optional_id;
char			*buf;
int			len;
char			*field;
char			*str;
int			max_len;
t_field			*fields; /* NULL terminated array */
{
  t_field		*fieldptr;
  
  fieldptr = NULL;
  while (fields->name)
    {
      if (!strcmp(fields->name,field))
	fieldptr = fields; 
      fields++;
    }
  if (!fieldptr)
    return (ERR_PAT_NO_SUCH_FIELD);
  return (get_field_to_str(buf,
			   len,
			   fieldptr,
			   str,
			   max_len));
}

t_status		pat_set_field_generic(optional_id,
					      buf,
					      len,
					      field,
					      value,
					      fields) 
t_id			*optional_id;
char			*buf;
int			len;
char			*field;
char			*value;	 /* Value string */	
t_field			*fields; /* NULL terminated array */
{
  t_field		*fieldptr;
  
  fieldptr = NULL;
  while (fields->name)
    {
      if (!strcmp(fields->name,field))
	fieldptr = fields;
      fields++;
    }
  if (!fieldptr)
    return (ERR_PAT_NO_SUCH_FIELD);
  return (set_field_from_str(buf,
			     len,
			     fieldptr,
			     value));
}

t_status		pat_get_fields_generic(vec_str,fields)
t_vec			*vec_str;    /* Vector of strings */
t_field			*fields; /* NULL terminated array */ 
{
  t_status		status;
  
  while (fields->name)
    {
      if ((status = vec_str_add(vec_str,
				fields->name)) != 0)
	return (status);
      fields++;
    }
  return (0);
}

t_status		pat_get_itmpl_generic(id,
					      buf,
					      len,
					      str,
					      max_len,
					      chan,
					      itmpl) 
t_id			*id;
char			*buf;
int			len;
char			*str;
int			max_len;
VOID_PTR		chan;
char			*itmpl;		/* I template */
{
  t_hash_elt		*he;
  int			i;
  t_status		status;

  if (he = id_get(id,
		  chan))
    i = (int)(he->value);
  else
    i = 0;
  if ((status = itmpl_format(i,
			     itmpl,
			     str,
			     max_len)) != 0)
     return (status);
  if ((status = id_override(id,
			    chan,
			    (VOID_PTR)(++i))) != 0)
    return (status);
  return (0);
}

t_status		pat_get_itmpl2_generic(id,
					       buf,
					       len,
					       str,
					       max_len,
					       chan,
					       itmpl) 
t_id			*id;
char			*buf;
int			len;
char			*str;
int			max_len;
VOID_PTR		chan;
char			*itmpl;		/* I template */
{
  t_hash_elt		*he;
  int			i;
  t_status		status;

  if (he = id_get(id,
		  chan))
    i = (int)(he->value);
  else
    i = 0;
  if ((status = itmpl_format(i,
			     itmpl,
			     str,
			     max_len)) != 0)
     return (status);
  return (0);
}

t_status	pat_get_field_pat_generic(field,
					  pat_return,
					  data_return,
					  fields) 
char		*field;
t_pat		**pat_return;
VOID_PTR	*data_return;
t_field		*fields; /* NULL terminated array */
{
  while (fields->name)
    {
      if (!strcmp(field,fields->name))
	{
	  (*pat_return) = fields->pat;
	  (*data_return) = fields->data;
	  return (0);
	}
      fields++;
    }
  return (ERR_PAT_NO_SUCH_FIELD);
}

#ifdef DEBUG
#ifdef HAVE_STDARG_H
VOID_FUNC	pat_print(t_pat *pat,char *fmt,...)
#else
VOID_FUNC	pat_print(pat,fmt,va_alist)
t_pat		*pat;
char		*fmt;
va_dcl
#endif
{
  va_list	ap;
  char		buf[BUFSIZ];
  char		*err;
  char		name[STR_BUFSIZ];
  t_status	status;

  assert(fmt);
#ifdef HAVE_STDARG_H
  va_start(ap,fmt);
#else
  va_start(ap);
  va_arg(ap,t_pat *);
  va_arg(ap,char *);
#endif
  vsnprintf(buf,sizeof (buf),fmt,ap);
  name[0] = 0;
  assert(pat->name_proc);
  status = pat->name_proc(NULL,
			  NULL,
			  name,
			  sizeof (name));
  
  fprintf(stderr,"pat_methods: %s::%s",name,buf);
  va_end(ap);
}
#endif
