static void init(grib_accessor* a, const long len, grib_arguments *arg )
{
	grib_accessor_padtomultiple* self = (grib_accessor_padtomultiple*)a;

	self->begin    =  grib_arguments_get_expression(a->parent->h, arg,0);
	self->multiple = grib_arguments_get_expression(a->parent->h, arg,1);
	a->length         = preferred_size(a,1);
}
static void init(grib_accessor* a,const long l, grib_arguments* c)
{
    grib_accessor_bits* self = (grib_accessor_bits*)a;
    grib_expression* e=NULL;
    int n = 0;

    self->argument = grib_arguments_get_name(grib_handle_of_accessor(a),c,n++);
    self->start    = grib_arguments_get_long(grib_handle_of_accessor(a),c,n++);
    self->len    = grib_arguments_get_long(grib_handle_of_accessor(a),c,n++);
    e=grib_arguments_get_expression(grib_handle_of_accessor(a),c,n++);
    if (e) {
        grib_expression_evaluate_double(grib_handle_of_accessor(a),e,&(self->referenceValue));
        self->referenceValuePresent=1;
    } else {
        self->referenceValuePresent=0;
    }
    self->scale = 1;
    if (self->referenceValuePresent) {
        self->scale=grib_arguments_get_double(grib_handle_of_accessor(a),c,n++);
    }

    Assert(self->len <= sizeof(long)*8);

    a->length=0;
}
static void init(grib_accessor* a, const long len , grib_arguments* arg )
{
    grib_accessor_md5* self = (grib_accessor_md5*)a;
  char* b=0;
    int n=0;
  grib_string_list* current=0;
  grib_context* context=a->context;

    self->offset = grib_arguments_get_name(grib_handle_of_accessor(a),arg,n++);
  self->length = grib_arguments_get_expression(grib_handle_of_accessor(a),arg,n++);
  self->blacklist=0;
  while ( (b=(char*)grib_arguments_get_name(grib_handle_of_accessor(a),arg,n++)) !=NULL) {
    if (! self->blacklist) {
      self->blacklist=(grib_string_list*)grib_context_malloc_clear(context,sizeof(grib_string_list));
      self->blacklist->value=grib_context_strdup(context,b);
      current=self->blacklist;
    } else {
      current->next=(grib_string_list*)grib_context_malloc_clear(context,sizeof(grib_string_list));
      current->next->value=grib_context_strdup(context,b);
      current=current->next;
    }
  }
    a->length = 0;
    a->flags |= GRIB_ACCESSOR_FLAG_READ_ONLY;
    a->flags |= GRIB_ACCESSOR_FLAG_EDITION_SPECIFIC;

}
static void init(grib_accessor* a, const long len, grib_arguments *arg )
{
  grib_accessor_lookup* self = (grib_accessor_lookup*)a;
  a->length = 0;
  self->llength = len;
  self->loffset = grib_arguments_get_long(a->parent->h,arg,0);
  a->flags |= GRIB_ACCESSOR_FLAG_READ_ONLY;
  self->real_name = grib_arguments_get_expression(a->parent->h,arg,1);
}
static void init(grib_accessor* a, const long len, grib_arguments* params) {
  int n=0;
  grib_accessor_codetable* self  = (grib_accessor_codetable*)a;
  grib_action* act=(grib_action*)(a->creator);

  self->tablename = grib_arguments_get_string(a->parent->h,params,n++);
  self->masterDir = grib_arguments_get_name(a->parent->h,params,n++);
  self->localDir = grib_arguments_get_name(a->parent->h,params,n++);

  /*if (a->flags & GRIB_ACCESSOR_FLAG_STRING_TYPE)
    printf("-------- %s type string (%ld)\n",a->name,a->flags);*/

  if (a->flags & GRIB_ACCESSOR_FLAG_TRANSIENT) {
    a->length = 0;
	if (!a->vvalue) 
		a->vvalue = grib_context_malloc_clear(a->parent->h->context,sizeof(grib_virtual_value));
    a->vvalue->type=grib_accessor_get_native_type(a);
    a->vvalue->length=len;
    if (act->default_value!=NULL) {
      const char* p = 0;
      size_t len = 1;
      long l;
      int ret=0;
      double d;
      char tmp[1024];
      grib_expression* expression=grib_arguments_get_expression(a->parent->h,act->default_value,0);
      int type = grib_expression_native_type(a->parent->h,expression);
      switch(type) {
        case GRIB_TYPE_DOUBLE:
          grib_expression_evaluate_double(a->parent->h,expression,&d);
          grib_pack_double(a,&d,&len);
          break;

        case GRIB_TYPE_LONG:
          grib_expression_evaluate_long(a->parent->h,expression,&l);
          grib_pack_long(a,&l,&len);
          break;

        default:
          len = sizeof(tmp);
          p = grib_expression_evaluate_string(a->parent->h,expression,tmp,&len,&ret);
          if (ret != GRIB_SUCCESS) {
			  grib_context_log(a->parent->h->context,GRIB_LOG_FATAL,
							   "unable to evaluate %s as string",a->name);
          }
          len = strlen(p)+1;
          pack_string(a,p,&len);
          break;
      }
    }
  } else
    a->length = len;

}
static int unpack_long(grib_accessor* a, long* val, size_t *len)
{
  int ret=0;
  grib_accessor_evaluate* self = (grib_accessor_evaluate*)a;
  grib_expression* e = grib_arguments_get_expression(a->parent->h,self->arg,0);


  ret = grib_expression_evaluate_long(a->parent->h,e,val);
  *len = 1;

  return ret;
}
static int notify_change(grib_action* act, grib_accessor * notified, grib_accessor* changed)
{
    if(act->default_value)
        return grib_pack_expression(notified,grib_arguments_get_expression(grib_handle_of_accessor(notified),act->default_value,0));
    return GRIB_SUCCESS;
}
int grib_init_accessor_from_handle(grib_loader* loader,grib_accessor* ga,grib_arguments* default_value)
{
	grib_handle* h = (grib_handle*)loader->data;
	int ret = GRIB_SUCCESS;
	size_t len = 0;
	char*   sval = NULL;
	unsigned char*   uval = NULL;
	long*   lval = NULL;
	double* dval = NULL;
	static int first  = 1;
	static const char* missing = 0;
	const char* name = NULL;
	int k = 0;
	grib_handle *g;
	int e, pack_missing = 0;
	grib_context_log(h->context,GRIB_LOG_DEBUG, "XXXXX Copying  %s",   ga->name);

	if(default_value)
	{
		grib_context_log(h->context,GRIB_LOG_DEBUG, "Copying:  setting %s to default value",
				ga->name);
		grib_pack_expression(ga,grib_arguments_get_expression(h,default_value,0));
	}

	if( (ga->flags & GRIB_ACCESSOR_FLAG_NO_COPY)  ||
		 ((ga->flags & GRIB_ACCESSOR_FLAG_EDITION_SPECIFIC) &&
					loader->changing_edition )        ||
		 (ga->flags & GRIB_ACCESSOR_FLAG_FUNCTION) ||
		 ( (ga->flags & GRIB_ACCESSOR_FLAG_READ_ONLY) &&
					!(ga->flags & GRIB_ACCESSOR_FLAG_COPY_OK) ) )
	{
		grib_context_log(h->context,GRIB_LOG_DEBUG, "Copying %s ignored",   ga->name);
		return GRIB_SUCCESS;
	}

#if 0
	if(h->values)
		if(copy_values(h,ga) == GRIB_SUCCESS)
		{
			grib_context_log(h->context,GRIB_LOG_DEBUG, "Copying: setting %s to multi-set-value",   ga->name);
			return GRIB_SUCCESS;
		}
#endif

#if 0
	if(h->loader)
		h->loader->init_accessor(h->loader,ga,default_value);
#else
	/* COMEBACK here
     this is needed if we reparse during reparse....
	 */

	g = h;
	while(g)
	{
		if(g->values) {
			if(copy_values(g,ga) == GRIB_SUCCESS) {
				grib_context_log(h->context,GRIB_LOG_DEBUG, "Copying: setting %s to multi-set-value",   ga->name);
				return GRIB_SUCCESS;
			}
		}
		g = g->main;
	}
#endif

	/* Check if the same name exists in the original message ... */
	k = 0;
	while( (k < MAX_ACCESSOR_NAMES)            &&
			((name = ga->all_names[k]) != NULL) &&
			((ret = grib_get_size(h,name,&len)) != GRIB_SUCCESS)) k++;

	if(ret != GRIB_SUCCESS)
	{
		name = ga->name;

		if(first)
		{
			missing = getenv("GRIB_PRINT_MISSING");
			first = 0;
		}

		grib_context_log(h->context,GRIB_LOG_DEBUG, "Copying [%s] failed: %s",
				name,grib_get_error_message(ret));

		if(missing)
		{
			fprintf(stdout,"REPARSE: no value for %s",name);
			if(default_value)
				fprintf(stdout," (default value)");
			fprintf(stdout,"\n");
		}

		return GRIB_SUCCESS;
	}

	/* we copy also virtual keys*/
	if(len == 0) {
		grib_context_log(h->context,GRIB_LOG_DEBUG, "Copying %s failed, length is 0",   name);
		return GRIB_SUCCESS;
	}

	if((ga->flags & GRIB_ACCESSOR_FLAG_CAN_BE_MISSING) && grib_is_missing(h,name,&e) && e == GRIB_SUCCESS && len == 1)
	{
		grib_pack_missing(ga);
		pack_missing = 1;
	}

	switch(grib_accessor_get_native_type(ga))
	{
	case GRIB_TYPE_STRING:

		/* len = len > 1024 ? len : 1024; */
		grib_get_string_length(h,name,&len);
		sval = (char*)grib_context_malloc(h->context,len);
		ret = grib_get_string_internal(h,name,sval,&len);
		if(ret == GRIB_SUCCESS)
		{
			grib_context_log(h->context,GRIB_LOG_DEBUG, "Copying string %s to %s",  sval, name);
			ret = grib_pack_string(ga,sval,&len);
		}
		grib_context_free(h->context,sval);

		break;

	case GRIB_TYPE_LONG:
		lval = (long*)grib_context_malloc(h->context,len*sizeof(long));
		ret = grib_get_long_array_internal(h,name,lval,&len);
		if(ret == GRIB_SUCCESS)
		{
			grib_context_log(h->context,GRIB_LOG_DEBUG, "Copying %d long(s) %d to %s",  len, lval[0], name);
			if(ga->same)
			{
				ret = grib_set_long_array(ga->parent->h,ga->name,lval,len);

				/* Allow for lists to be resized */
				if((ret == GRIB_WRONG_ARRAY_SIZE || ret == GRIB_ARRAY_TOO_SMALL) && loader->list_is_resized)
					ret = GRIB_SUCCESS;
			}
			else
			{
			    /* See GRIB-492. This is NOT an ideal solution! */
			    if (*lval == GRIB_MISSING_LONG || pack_missing)
			    {
			        ;        /* No checks needed */
			    }
			    else
			    {
			        /* If we have just one key of type long which has one octet, then do not exceed maximum value */
			        const long num_octets = ga->length;
			        if (len == 1 && num_octets == 1 && *lval > 255)
			        {
			            *lval = 0; /* Reset to a reasonable value */
			        }
			    }
				ret = grib_pack_long(ga,lval,&len);
			}
		}

		grib_context_free(h->context,lval);

		break;

	case GRIB_TYPE_DOUBLE:
		dval = (double*)grib_context_malloc(h->context,len*sizeof(double));
		ret = grib_get_double_array_internal(h,name,dval,&len);
		if(ret == GRIB_SUCCESS)
		{
			grib_context_log(h->context,GRIB_LOG_DEBUG, "Copying %d double(s) %g to %s",  len, dval[0], name);
			if(ga->same)
			{
				ret = grib_set_double_array(ga->parent->h,ga->name,dval,len);

				/* Allow for lists to be resized */
				if((ret == GRIB_WRONG_ARRAY_SIZE || ret == GRIB_ARRAY_TOO_SMALL) && loader->list_is_resized)
					ret = GRIB_SUCCESS;
			}
			else ret = grib_pack_double(ga,dval,&len);
		}

		grib_context_free(h->context,dval);
		break;

	case GRIB_TYPE_BYTES:

		uval = (unsigned char*)grib_context_malloc(h->context,len*sizeof(char));
		ret = grib_get_bytes_internal(h,name,uval,&len);
		if(ret == GRIB_SUCCESS)
		{
			grib_context_log(h->context,GRIB_LOG_DEBUG, "Copying %d byte(s) to %s",  len, name);
			ret = grib_pack_bytes(ga,uval,&len);
		}

		grib_context_free(h->context,uval);

		break;

	case GRIB_TYPE_LABEL:
		break;

	default:
		grib_context_log(h->context,GRIB_LOG_ERROR, "Copying %s, cannot establish type %d [%s]"
				, name,grib_accessor_get_native_type(ga),ga->creator->cclass->name);
		break;
	}

	return ret;

}
static int pack_string(grib_accessor* a, const char* buffer, size_t *len)
{
  grib_accessor_codetable* self = (grib_accessor_codetable*)a;
  grib_codetable*          table ;

  long i;
  size_t size = 1;

  typedef int (*cmpproc)(const char*, const char*);

  cmpproc cmp = a->flags | GRIB_ACCESSOR_FLAG_LOWERCASE ? strcasecmp : strcmp;

  if(!self->table) self->table = load_table(self);
  table=self->table;

  if(!table)
    return GRIB_ENCODING_ERROR;

  if (a->set) {
	  int err=grib_set_string(a->parent->h,a->set,buffer,len);
	  if (err!=0) return err;
  }

  for(i = 0 ; i < table->size; i++)
    if(table->entries[i].abbreviation)
		  if(cmp(table->entries[i].abbreviation,buffer) == 0)
        return grib_pack_long(a,&i,&size);

  if (a->flags & GRIB_ACCESSOR_FLAG_NO_FAIL) {
	  grib_action* act=(grib_action*)(a->creator);
	  if (act->default_value!=NULL) {
		  const char* p = 0;
		  size_t len = 1;
		  long l;
		  int ret=0;
		  double d;
		  char tmp[1024];
		  grib_expression* expression=grib_arguments_get_expression(a->parent->h,act->default_value,0);
		  int type = grib_expression_native_type(a->parent->h,expression);
		  switch(type) {
			  case GRIB_TYPE_DOUBLE:
				  grib_expression_evaluate_double(a->parent->h,expression,&d);
				  grib_pack_double(a,&d,&len);
				  break;

			  case GRIB_TYPE_LONG:
				  grib_expression_evaluate_long(a->parent->h,expression,&l);
				  grib_pack_long(a,&l,&len);
				  break;

			  default:
				  len = sizeof(tmp);
				  p = grib_expression_evaluate_string(a->parent->h,expression,tmp,&len,&ret);
				  if (ret != GRIB_SUCCESS) {
					  grib_context_log(a->parent->h->context,GRIB_LOG_FATAL,
									   "unable to evaluate %s as string",a->name);
					  return ret;
				  }
				  len = strlen(p)+1;
				  pack_string(a,p,&len);
				  break;
		  }
		  return GRIB_SUCCESS;
	  }
	
  }
  return GRIB_ENCODING_ERROR;
}
int grib_init_accessor_from_array(grib_loader* loader,grib_accessor* ga,grib_arguments* default_value)
{
  grib_handle* h = ga->parent->h;
  int retval =GRIB_SUCCESS;
  char* strvalue;
  size_t len=0;
  int type=0;
  double* dvalue=0;
  long* lvalue=0;
  long lval=0;
  double dval=0;
  int i=0;
  grib_associative_array* ar=NULL;
  grib_runtime_type* value=NULL;

  ar=(grib_associative_array*)loader->data;

  grib_context_log(h->context,GRIB_LOG_DEBUG, "Initialize  %s",   ga->name);

  retval= grib_associative_array_get(ar,ga->name,&value);

  if((retval != GRIB_ARRAY_SUCCESS) && default_value) {
      grib_context_log(h->context,GRIB_LOG_DEBUG, "Setting %s to default value", ga->name);
      grib_pack_expression(ga,grib_arguments_get_expression(h,default_value,0));
      return GRIB_SUCCESS;
  }

  if(ga->flags & GRIB_ACCESSOR_FLAG_READ_ONLY)
  {
    grib_context_log(h->context,GRIB_LOG_DEBUG, "Setting  %s  ignored (read only)",   ga->name);
    return GRIB_SUCCESS;
  }

  if (retval != GRIB_ARRAY_SUCCESS) {
    grib_context_log(h->context,GRIB_LOG_DEBUG,
        "Grib array error %d",retval);
    if ((ga->flags & GRIB_ACCESSOR_FLAG_CAN_BE_MISSING)) {
      grib_context_log(h->context,GRIB_LOG_DEBUG,
        "Setting  %s  ignored (optional or can be missing)",   ga->name);
      return GRIB_SUCCESS;
    } else {
      grib_context_log(h->context,GRIB_LOG_ERROR, "%s  required",   ga->name);
      return retval;
    }
  }

  if (value && grib_runtimetype_get_type(value,&type) == GRIB_RUNTIMETYPE_SUCCESS) {
    if (type == GRIB_RUNTIMETYPE_CHAR ) {
      grib_runtimetype_get_char(value,&strvalue,&len);
        switch(grib_accessor_get_native_type(ga))  {

          case GRIB_TYPE_STRING:
            grib_context_log(h->context,GRIB_LOG_DEBUG, "Setting %s to string %s",
                              ga->name, strvalue);
            grib_set_string_internal(h,ga->name,strvalue,&len);
            break;

          case GRIB_TYPE_LONG:
           if (!strcmp(strvalue,"MISSING")) lval=GRIB_MISSING_LONG;
           else lval=atol(strvalue);
           grib_context_log(h->context,GRIB_LOG_DEBUG, "Setting %s to long %d", ga->name, lval);
           grib_set_long_internal(h,ga->name,lval);
           break;

          case GRIB_TYPE_DOUBLE:
           if (!strcmp(strvalue,"MISSING")) dval=GRIB_MISSING_DOUBLE;
           else if (sscanf(strvalue,"%lg",&dval)!=1) {
             grib_context_log(h->context,GRIB_LOG_ERROR, "Unable to set %s wrong value format",   ga->name);
           }
           grib_context_log(h->context,GRIB_LOG_DEBUG, "Setting %s to double %lg (%s)", ga->name, dval,strvalue);
           grib_set_double_internal(h,ga->name,dval);
           break;

          case GRIB_TYPE_BYTES:
           grib_context_log(h->context,GRIB_LOG_DEBUG, "Setting %s to string %s",
                            ga->name, strvalue);
           grib_set_bytes_internal(h,ga->name,(unsigned char*)strvalue,&len);
           break;

         case GRIB_TYPE_LABEL:
           break;

         default:
           grib_context_log(h->context,GRIB_LOG_ERROR, "Setting %s, cannot establish type %d [%s]"
            , ga->name,grib_accessor_get_native_type(ga),ga->creator->cclass->name);
           break;
        }
   } else {

      if (grib_runtimetype_get_double(value,&dvalue,&len) == GRIB_RUNTIMETYPE_SUCCESS) {
        switch(grib_accessor_get_native_type(ga))  {

          case GRIB_TYPE_LONG:
           lvalue=(long*)malloc(sizeof(long)*len);
           for (i=0;i<len;i++) lvalue[i]=(long)dvalue[i];
           grib_context_log(h->context,GRIB_LOG_DEBUG, "Setting long array %s",ga->name);
           grib_set_long_array(h,ga->name,lvalue,len);
           free(lvalue);
           break;

          case GRIB_TYPE_DOUBLE:
           grib_context_log(h->context,GRIB_LOG_DEBUG, "Setting double array %s",ga->name);
           grib_set_double_array(h,ga->name,dvalue,len);
           break;

          default:
           grib_context_log(h->context,GRIB_LOG_ERROR, "Setting array %s, wrong type [%d]"
            , ga->name,grib_accessor_get_native_type(ga));
           break;
         }

      } else
          grib_context_log(h->context,GRIB_LOG_ERROR, "Unable to set %s to double, wrong type (%d)",
          ga->name,type);
    }
#if 0
    switch(grib_accessor_get_native_type(ga))
    {
      case GRIB_TYPE_STRING:
        if (grib_runtimetype_get_char(value,&strvalue,&strvalue_size) == GRIB_RUNTIMETYPE_SUCCESS) {
          grib_context_log(h->context,GRIB_LOG_DEBUG, "Setting %s to string %s",
          ga->name, strvalue);
          len=strlen(strvalue);
          grib_set_string_internal(h,ga->name,strvalue,&len);
        } else
          grib_context_log(h->context,GRIB_LOG_ERROR, "Unable to set %s to string, wrong type",
          ga->name);
        break;

      case GRIB_TYPE_LONG:
        if (grib_runtimetype_get_long(value,&lval,&len) == GRIB_RUNTIMETYPE_SUCCESS) {
          grib_context_log(h->context,GRIB_LOG_DEBUG, "Setting %s to long %d", ga->name, lval);
          grib_set_long_internal(h,ga->name,*lval);
        } else
          grib_context_log(h->context,GRIB_LOG_ERROR, "Unable to set %s to long, wrong type",
          ga->name);
        break;

      case GRIB_TYPE_DOUBLE:
        if (grib_runtimetype_get_double(value,&dval,&len) == GRIB_RUNTIMETYPE_SUCCESS) {
          grib_context_log(h->context,GRIB_LOG_DEBUG, "Setting %s to long %d", ga->name, dval);
          grib_set_double_internal(h,ga->name,*dval);
        } else
          grib_context_log(h->context,GRIB_LOG_ERROR, "Unable to set %s to double, wrong type",
          ga->name);
        break;

      case GRIB_TYPE_BYTES:
        if (grib_runtimetype_get_char(value,&strvalue,&len) == GRIB_RUNTIMETYPE_SUCCESS) {
          grib_context_log(h->context,GRIB_LOG_DEBUG, "Setting %s to string %s",
          ga->name, strvalue);
          grib_set_bytes_internal(h,ga->name,(unsigned char*)strvalue,&len);
        } else
          grib_context_log(h->context,GRIB_LOG_ERROR, "Unable to set %s to string, wrong type",
          ga->name);
        break;

      case GRIB_TYPE_LABEL:
        break;

      default:
        grib_context_log(h->context,GRIB_LOG_ERROR, "Setting %s, cannot establish type %d [%s]"
            , ga->name,grib_accessor_get_native_type(ga),ga->creator->cclass->name);
        break;
    }
#endif

  }

  return retval;

}