/* ==================================================================== * Copyright 1999 Web Juice, LLC. All rights reserved. * * tagplist.c * * Functions for manipulating the tag pair list structure in the template * library. * * ==================================================================== */ #include #include #include /* ==================================================================== * NAME: tagplist_init * * DESCRIPTION: Initializes and returns a pointer to a new tag pair * list structure. * * RETURN VALUES: Returns NULL if the memory allocation fails; otherwise * returns a pointer to a tag pair list structure. * * BUGS: Hopefully none. * ==================================================================== */ tagplist_p tagplist_init() { tagplist_p tag_pair_list; tag_pair_list = (tagplist_p)malloc(sizeof(tagplist)); if (tag_pair_list == NULL) { template_errno = TMPL_EMALLOC; return NULL; } tag_pair_list->open_name = NULL; tag_pair_list->close_name = NULL; tag_pair_list->function = NULL; tag_pair_list->next = NULL; tag_pair_list->named_context = 0; return(tag_pair_list); } /* ==================================================================== * NAME: tagplist_destroy * * DESCRIPTION: Frees up all memory associated with a tag pair list. * * 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 tagplist_destroy(tagplist_p tag_pair_list) { tagplist_p next; if (tag_pair_list == NULL) { return; } next = tag_pair_list->next; tag_pair_list->next = NULL; if (tag_pair_list->open_name != NULL) { free(tag_pair_list->open_name); } if (tag_pair_list->close_name != NULL) { free(tag_pair_list->close_name); } free(tag_pair_list); tagplist_destroy(next); } /* ==================================================================== * NAME: tagplist_alias * * DESCRIPTION: Copy an existing tag pair to a new tag pair name. * * RETURN VALUES: Returns 0 upon failure; 1 on success. * * BUGS: Hopefully none. * ==================================================================== */ int tagplist_alias(tagplist_p *tag_pair_list, char *old_open_name, char *old_close_name, char *new_open_name, char *new_close_name) { tagplist_p current = *tag_pair_list; /* Make sure the names are not NULL */ if ((old_open_name == NULL) || (old_close_name == NULL) || (new_open_name == NULL) || (new_close_name == NULL)) { template_errno = TMPL_ENULLARG; return 0; } /* Walk through the contexts to find the old tag */ while (current != NULL) { if ((current->open_name != NULL) && (current->close_name != NULL) && (strcmp(current->open_name, old_open_name) == 0) && (strcmp(current->close_name, old_close_name) == 0)) { return tagplist_register(tag_pair_list, current->named_context, new_open_name, new_close_name, current->function); } current = current->next; } template_errno = TMPL_ENOTAGP; return 0; } /* ==================================================================== * NAME: tagplist_remove * * DESCRIPTION: Remove a tag pair. * * RETURN VALUES: None. * * BUGS: Hopefully none. * ==================================================================== */ void tagplist_remove(tagplist_p *tag_pair_list, char *open_name) { tagplist_p current = *tag_pair_list; tagplist_p previous = NULL; /* Make sure the name isn't NULL */ if (open_name == NULL) { template_errno = TMPL_ENULLARG; return; } /* Make sure the pointer passed in wasn't NULL */ if (*tag_pair_list == NULL) { template_errno = TMPL_ENULLARG; return; } while (current != NULL) { if ((current->open_name != NULL) && (strcmp(current->open_name, open_name) == 0)) { break; } previous = current; current = current->next; } /* The tag wasn't found */ if (current == NULL) { return; } /* Move a pointer to skip the found tag */ if (previous == NULL) { *tag_pair_list = current->next; } else { previous->next = current->next; } /* Destroy the tag */ current->next = NULL; if (current->open_name != NULL) { free(current->open_name); } if (current->close_name != NULL) { free(current->close_name); } free(current); } /* ==================================================================== * NAME: tagplist_register * * DESCRIPTION: Register a new tag pair and associated function to call. * * RETURN VALUES: Returns 0 upon failure; 1 on success. * * BUGS: Hopefully none. * ==================================================================== */ int tagplist_register(tagplist_p *tag_pair_list, char named_context, char *open_name, char *close_name, void (*function) (context_p, int, char**)) { tagplist_p new = NULL; int length; /* Make sure the function isn't NULL */ if (function == NULL) { template_errno = TMPL_ENULLARG; return 0; } if ((open_name == NULL) || (close_name == NULL)) { template_errno = TMPL_ENULLARG; return 0; } if (*tag_pair_list == NULL) { template_errno = TMPL_ENULLARG; return 0; } new = tagplist_init(); new->function = function; new->named_context = named_context; length = strlen(open_name); new->open_name = (char *)malloc(length + 1); strncpy(new->open_name, open_name, length); new->open_name[length] = '\0'; length = strlen(close_name); new->close_name = (char *)malloc(length + 1); strncpy(new->close_name, close_name, length); new->close_name[length] = '\0'; new->next = *tag_pair_list; *tag_pair_list = new; return 1; } /* ==================================================================== * NAME: tagplist_is_opentag * * DESCRIPTION: Find out whether a particular tag is a legitimate * opening tag. * * RETURN VALUES: Returns 0 if there's a problem or if the name is not * a valid opening tag, or 1 if the name is a valid tag. * * BUGS: Hopefully none. * ==================================================================== */ int tagplist_is_opentag(tagplist_p tag_pair_list, char *open_name) { tagplist_p current = tag_pair_list; while (current != NULL) { if ((current->open_name != NULL) && (current->function != NULL) && (strcmp(current->open_name, open_name) == 0)) { return 1; } current = current->next; } template_errno = TMPL_ENOTAGP; return 0; } /* ==================================================================== * NAME: tagplist_is_closetag * * DESCRIPTION: Find out whether a particular tag is a valid closing * tag for another (i.e. whether you have a valid tag pair). * * RETURN VALUES: Returns 0 if there's a problem or if the names do not * form a valid tag pair; otherwise returns 1. * * BUGS: Hopefully none. * ==================================================================== */ int tagplist_is_closetag(tagplist_p tag_pair_list, char *open_name, char *close_name) { tagplist_p current = tag_pair_list; while (current != NULL) { if ((current->open_name != NULL) && (current->close_name != NULL) && (strcmp(current->open_name, open_name) == 0) && (strcmp(current->close_name, close_name) == 0)) { return 1; } current = current->next; } template_errno = TMPL_ENOTAGP; return 0; } /* ==================================================================== * NAME: tagplist_exec * * DESCRIPTION: Executes the function associated with a given tag pair. * * RETURN VALUES: Returns NULL if there's a problem or the context * modified by the function otherwise. * * BUGS: Hopefully none. * ==================================================================== */ context_p tagplist_exec(tagplist_p tag_pair_list, char *open_name, context_p ctx, int argc, char **argv) { tagplist_p current = tag_pair_list; while (current != NULL) { if ((current->open_name != NULL) && (current->function != NULL) && (strcmp(current->open_name, open_name) == 0)) { if ((current->named_context) && (argc >= 0)) { context_p named_context; named_context = context_get_named_child(ctx, argv[1]); if (named_context == NULL) { named_context = context_get_anonymous_child(ctx); if (named_context == NULL) { return NULL; } ctx_unset_output(named_context); return(named_context); } current->function(named_context, argc, argv); return(named_context); } else { context_p anonymous_context; anonymous_context = context_get_anonymous_child(ctx); if (anonymous_context == NULL) { return NULL; } current->function(anonymous_context, argc, argv); return(anonymous_context); } } current = current->next; } template_errno = TMPL_ENOTAGP; return NULL; }