/* ====================================================================
* Copyright 1999 Web Juice, LLC. All rights reserved.
*
* context.c
*
* Functions for manipulating the context structure in the template
* library.
*
* ==================================================================== */
#include <stdlib.h>
#include <context.h>
#include <varlist.h>
#include <nclist.h>
/* ====================================================================
* NAME: context_init
*
* DESCRIPTION: Initializes and returns a pointer to a new context
* structure.
*
* RETURN VALUES: Returns NULL if the memory allocation fails; otherwise
* returns a pointer to a varlist structure.
*
* BUGS: Hopefully none.
* ==================================================================== */
context_p
context_init(
void
)
{
context_p ctx;
ctx = (context_p)
calloc
(1,
sizeof
(context));
if
(ctx == NULL)
{
return
NULL;
}
ctx->variables = varlist_init();
if
(ctx->variables == NULL)
{
free
(ctx);
return
NULL;
}
ctx->named_child_contexts = nclist_init();
if
(ctx->named_child_contexts == NULL)
{
varlist_destroy(ctx->variables);
free
(ctx);
return
NULL;
}
ctx->parent_context = NULL;
ctx->next_context = NULL;
ctx->output_contents = 1;
ctx->anonymous = 0;
return
(ctx);
}
/* ====================================================================
* NAME: context_destroy
*
* DESCRIPTION: Frees up all memory associated with a context.
*
* RETURN VALUES: None.
*
* BUGS: Because a free()d pointer still *looks* valid, it is
* difficult to protect against the problems that arise
* if the user calls this function too early.
* ==================================================================== */
void
context_destroy(context_p ctx)
{
context_p next;
if
(ctx == NULL)
{
return
;
}
next = ctx->next_context;
if
(ctx->named_child_contexts != NULL)
{
nclist_destroy(ctx->named_child_contexts);
}
if
(ctx->variables != NULL)
{
varlist_destroy(ctx->variables);
}
ctx->named_child_contexts = NULL;
ctx->variables = NULL;
ctx->next_context = NULL;
ctx->parent_context = NULL;
free
(ctx);
context_destroy(next);
}
/* ====================================================================
* NAME: context_get_value
*
* DESCRIPTION: Returns the value of the variable stored under the given
* name in the current context or any parents' variable list.
*
* RETURN VALUES: This function will return NULL if there are any problems
* or if there is no value. It returns a string containing
* the value on success.
*
* BUGS: Hopefully none.
* ==================================================================== */
char
*
context_get_value(context_p ctx,
char
*name)
{
char
*result;
if
(ctx == NULL)
{
return
NULL;
}
result = varlist_get_value(ctx->variables, name);
if
(result != NULL)
{
return
(result);
}
if
(ctx->parent_context == NULL)
{
return
NULL;
}
return
(context_get_value(ctx->parent_context, name));
}
/* ====================================================================
* NAME: context_set_value
*
* DESCRIPTION: Set a variable in the context's variable list.
*
* RETURN VALUES: Returns 0 if there's any trouble. Returns 1 if the
* variable was successfully set.
*
* BUGS: Hopefully none.
* ==================================================================== */
int
context_set_value(context_p ctx,
char
*name,
char
*value)
{
if
(ctx == NULL)
{
return
0;
}
return
(varlist_set_value(ctx->variables, name, value));
}
/* ====================================================================
* NAME: context_get_anonymous_child
*
* DESCRIPTION: Creates and returns an unnamed context with the parent
* set to the current context (i.e. a new context within
* the scope of the current context).
*
* RETURN VALUES: Returns NULL if there's a problem; returns a pointer to
* the new context otherwise.
*
* BUGS: Hopefully none.
* ==================================================================== */
context_p
context_get_anonymous_child(context_p ctx)
{
context_p anonymous_ctx;
if
(ctx == NULL)
{
return
NULL;
}
anonymous_ctx = context_init();
if
(anonymous_ctx == NULL)
{
return
NULL;
}
anonymous_ctx->parent_context = ctx;
anonymous_ctx->anonymous = 1;
return
(anonymous_ctx);
}
/* ====================================================================
* NAME: context_get_named_child
*
* DESCRIPTION: This function returns a named context within the scope
* of the current context, if it exists.
*
* RETURN VALUES: Returns NULL if there is any problem, or if the context
* doesn't exist; else returns a pointer to the context.
*
* BUGS: Hopefully none.
* ==================================================================== */
context_p
context_get_named_child(context_p ctx,
char
*name)
{
context_p result;
if
(ctx == NULL)
{
return
NULL;
}
result = nclist_get_context(ctx->named_child_contexts, name);
if
(result != NULL)
{
return
(result);
}
if
(ctx->parent_context == NULL)
{
return
NULL;
}
return
(context_get_named_child(ctx->parent_context, name));
}
/* ====================================================================
* NAME: context_set_named_child
*
* DESCRIPTION: This function creates a new named context within the
* scope of the current context.
*
* RETURN VALUES: Returns 0 if there is any trouble; returns 1 on success.
*
* BUGS: Hopefully none.
* ==================================================================== */
int
context_set_named_child(context_p ctx,
char
*name)
{
context_p named_ctx;
if
(ctx == NULL)
{
return
0;
}
if
(! nclist_new_context(ctx->named_child_contexts, name))
{
return
0;
}
named_ctx = context_get_named_child(ctx, name);
if
(named_ctx == NULL)
{
return
0;
}
named_ctx->parent_context = ctx;
return
1;
}
/* ====================================================================
* NAME: context_add_peer
*
* DESCRIPTION: This function adds a peer context (a.k.a. loop iteration)
* to the context passed in, and initializes it.
*
* RETURN VALUES: Returns NULL if there is any trouble; returns a pointer to
* the new peer context otherwise.
*
* BUGS: Hopefully none.
* ==================================================================== */
context_p
context_add_peer(context_p ctx)
{
context_p peer_ctx;
context_p current = ctx;
if
(ctx == NULL)
{
return
NULL;
}
peer_ctx = context_init();
if
(peer_ctx == NULL)
{
return
NULL;
}
peer_ctx->parent_context = ctx->parent_context;
while
(current->next_context != NULL)
{
current = current->next_context;
}
current->next_context = peer_ctx;
return
(peer_ctx);
}
/* ====================================================================
* NAME: context_output_contents
*
* DESCRIPTION: This function adds a peer context (a.k.a. loop iteration)
*
* RETURN VALUES: None.
*
* BUGS: Hopefully none.
* ==================================================================== */
void
context_output_contents(context_p ctx,
char
output_contents)
{
if
(ctx == NULL)
{
return
;
}
ctx->output_contents = output_contents;
return
;
}