/*
 * Copyright (c) 2003-2011
 * Distributed Systems Software.  All rights reserved.
 * See the file LICENSE for redistribution information.
 *
 * $Id: var.h 2528 2011-09-23 21:54:05Z brachman $
 */

#ifndef _VAR_H_
#define _VAR_H_

/*
 * These can't be any characters that can appear in the name of a namespace
 * or the name of a variable or flag.
 */
#define VAR_NS_SEP_STR		"::"

/* Variable reference modifier bit flags */
#define VAR_DEFAULT_FLAG		0			/* No flags */
#define VAR_EXISTS_FLAG			(1 << 0)	/* e */
#define VAR_NONEMPTY_FLAG		(1 << 1)	/* n */
#define VAR_EMPTY_FLAG			(1 << 2)	/* z */
#define VAR_ICASE_FLAG			(1 << 3)	/* i */
#define VAR_ALTVAL_FLAG			(1 << 4)	/* ? */
#define VAR_NALTVAL_FLAG		(1 << 5)	/* + */

typedef struct Var {
  char *varname;		/* Original variable name */
  char *ns;				/* Namespace */
  char *name;			/* Variable name relative to the namespace */
  char *flagstr;		/* Optional flag string */
  unsigned int flags;	/* Parsed flag string */
  char *altval;			/* Alt value for VAR_ALTVAL_FLAG/VAR_NALTVAL_FLAG */
} Var;

typedef struct Var2 {
  char *varname;		/* Original variable name */
  char *ns;				/* Namespace */
  char *name;			/* Variable name relative to the namespace */
  char *flagstr;		/* Optional flag string */
  unsigned int flags;	/* Parsed flag string */
  char *altval;			/* Alt value for VAR_ALTVAL_FLAG/VAR_NALTVAL_FLAG */
  Dsvec *refs;
} Var2;

typedef struct Var_ref {
  char *ns;				/* Namespace */
  char *varname;		/* Variable name in the namespace */
} Var_ref;

typedef struct Var_ns Var_ns;

/* Bit flags */
#define VAR_NS_DEFAULT			0			/* No flags */
#define VAR_NS_READONLY			(1 << 0)
#define VAR_NS_RESERVED			(1 << 1)
#define VAR_NS_TEMPORARY		(1 << 2)

struct Var_ns {
  char *ns;
  Kwv *kwv;
  unsigned int flags;
  Var_ns *prev;
  Var_ns *next;
};

typedef Ds *(*Var_resolve)(Var *var, void *, void *, int *);

#ifdef __cplusplus
extern "C" {
#endif

extern int var_ns_is_valid_varname(char *str, char **endp);
extern int var_ns_is_valid_namespace_name(char *str);
extern Var *var_parse_name(char *str, char **endp);
extern Var_ref *var_parse_ref(char *str);
extern Ds *var_expand(char *str, Var_resolve resolve, void *resolve_arg);
extern Ds *var_value(char *str, Var **var, char **endp,
					 Var_resolve resolve, void *resolve_arg);

extern Var_ns *var_ns_lookup(Var_ns *root, char *ns);
extern Var_ns *var_ns_new(Var_ns **root, char *ns, Kwv *kwv);
extern Var_ns *var_ns_add(Var_ns **root, Var_ns *v);
extern Var_ns *var_ns_create(char *name, Kwv *kwv);
extern int var_ns_replace(Var_ns **root, char *name, Kwv *kwv);
extern Kwv *var_ns_add_key(Var_ns *root, char *ns, char *key, char *val);
extern Kwv *var_ns_add_var(Var_ns *root, char *name, char *key, char *val,
						   void *xval);
extern int var_ns_delete(Var_ns **root, char *ns);
extern int var_ns_delete_temporaries(Var_ns **root);
extern Kwv_pair *var_ns_get_pair(Var_ns *root, char *ns, char *key);
extern char *var_ns_get_value(Var_ns *root, char *ns, char *key);
extern Kwv *var_ns_lookup_kwv(Var_ns *root, char *ns);
extern char *var_ns_names(Var_ns *root);
extern Var_ns *var_ns_copy(Var_ns *root);
extern Var_ns *var_ns_copy_exclude(Var_ns *root, Dsvec *exclude);
extern char *var_ns_buf(Var_ns *root, char *ns);
extern Var_ns *var_ns_from_env(char *ns_name);
extern char *var_ns_varname(char *ns, char *name);
extern int var_ns_is_readonly(Var_ns *root, char *ns_name);
extern int var_ns_is_reserved(Var_ns *root, char *ns_name);
extern unsigned int var_ns_set_flags(Var_ns *root, char *ns_name,
									 unsigned int flags);

#ifdef __cplusplus
}
#endif

#endif
