/* ==================================================================== * Copyright 1999 Web Juice, LLC. All rights reserved. * * default_tags.c * * The functions for the default tags shipped with the template library: * echo, include, comment/endcomment, if/endif, ifn/endifn, loop/endloop. * * ==================================================================== */ #include #include #include #include #include #include #include #include #include #include #include /* ==================================================================== * NAME: tag_pair_debug * * DESCRIPTION: The tag pair function for debug * * RETURN VALUES: None. * * BUGS: Hopefully none. * ==================================================================== */ void tag_pair_debug(context_p ctx, int argc, char **argv) { dump_context(ctx, context_root(ctx), 0); } /* ==================================================================== * NAME: tag_pair_if * * DESCRIPTION: The tag pair function for if/endif * * RETURN VALUES: None. * * BUGS: Hopefully none. * ==================================================================== */ void tag_pair_if(context_p ctx, int argc, char **argv) { if (argc != 1) { return; } context_output_contents(ctx, string_truth(argv[1])); return; } /* ==================================================================== * NAME: tag_pair_ifn * * DESCRIPTION: The tag pair function for ifn/endifn * * RETURN VALUES: None. * * BUGS: Hopefully none. * ==================================================================== */ void tag_pair_ifn(context_p ctx, int argc, char **argv) { if (argc != 1) { return; } context_output_contents(ctx, (! string_truth(argv[1]))); return; } /* ==================================================================== * NAME: tag_pair_loop * * DESCRIPTION: The tag pair function for loop/endloop * * RETURN VALUES: None. * * BUGS: Hopefully none. * ==================================================================== */ void tag_pair_loop(context_p ctx, int argc, char **argv) { return; } /* ==================================================================== * NAME: tag_pair_comment * * DESCRIPTION: The tag pair function for comment/endcomment * * RETURN VALUES: None. * * BUGS: Hopefully none. * ==================================================================== */ void tag_pair_comment(context_p ctx, int argc, char **argv) { context_output_contents(ctx, 0); return; } /* ==================================================================== * NAME: simple_tag_echo * * DESCRIPTION: The tag function for echo * * RETURN VALUES: None. * * BUGS: Hopefully none. * ==================================================================== */ void simple_tag_echo(context_p ctx, char **output, int argc, char **argv) { int total_size = 0; int i; if (argc < 1) { *output = NULL; return; } *output = NULL; for (i = 1; i <= argc; i++) { int size; char *t; if (argv[i] == NULL) { continue; } size = strlen(argv[i]); t = (char *)malloc(total_size + size + 1); if (*output == NULL) { strncpy(t, argv[i], size); t[size] = '\0'; } else { strcpy(t, *output); strcat(t, argv[i]); t[total_size + size] = '\0'; free(*output); } *output = t; total_size += size + 1; } return; } /* ==================================================================== * NAME: simple_tag_include * * DESCRIPTION: The tag function for include * * RETURN VALUES: None. * * BUGS: Hopefully none. * ==================================================================== */ void simple_tag_include(context_p ctx, char **output, int argc, char **argv) { struct stat finfo; FILE *filehandle; context_p rootctx = context_root(ctx); if (argc != 1) { *output = NULL; return; } if (stat(argv[1], &finfo) != 0) { char *dir = context_get_value(ctx, TMPL_VARNAME_DIR); int size = strlen(argv[1]) + strlen(dir) + 2; if (rootctx->bufsize < size) { if (rootctx->buffer != NULL) { free(rootctx->buffer); } rootctx->buffer = (char *)malloc(size); rootctx->bufsize = size; } strcpy(rootctx->buffer, dir); strcat(rootctx->buffer, argv[1]); (rootctx->buffer)[size - 1] = '\0'; if (stat(rootctx->buffer, &finfo) != 0) { *output = NULL; return; } } else { if (rootctx->bufsize < (strlen(argv[1] + 1))) { if (rootctx->buffer != NULL) { free(rootctx->buffer); } rootctx->buffer = (char *)malloc(strlen(argv[1]) + 1); rootctx->bufsize = strlen(argv[1] + 1); } strcpy(rootctx->buffer, argv[1]); } if ((filehandle = fopen(rootctx->buffer, "r")) == NULL) { *output = NULL; return; } *output = (char *)malloc(finfo.st_size + 1); if (*output == NULL) { return; } fread(*output, 1, finfo.st_size, filehandle); (*output)[finfo.st_size] = '\0'; fclose(filehandle); return; } /* ==================================================================== * NAME: template_loop_iteration * * DESCRIPTION: This function pre-builds loops via named contexts. * It is the end-user method for building loops. * * RETURN VALUES: Returns a context for this iteration. * * BUGS: Hopefully none. * ==================================================================== */ context_p template_loop_iteration(context_p ctx, char *loop_name) { context_p return_context; return_context = context_get_named_child(ctx, loop_name); if (return_context == NULL) { context_set_named_child(ctx, loop_name); return_context = context_get_named_child(ctx, loop_name); return(return_context); } return(context_add_peer(return_context)); } /* ==================================================================== * NAME: template_fetch_loop_iteration * * DESCRIPTION: This function returns a loop iteration context by * name and number from the given context, if it exists. * * RETURN VALUES: Returns an existing context, or NULL if there isn't * one. * * BUGS: Hopefully none. * ==================================================================== */ context_p template_fetch_loop_iteration(context_p ctx, char *loop_name, int iteration) { context_p named_child, current; int curi; named_child = context_get_named_child(ctx, loop_name); if (named_child == NULL) { return NULL; } curi = 0; current = named_child; while ((curi < iteration) && (current->next_context != NULL)) { ++curi; current = current->next_context; } if (curi == iteration) { return current; } else { template_errno = TMPL_ENOCTX; return NULL; } } /* ==================================================================== * NAME: string_truth * * DESCRIPTION: Decides whether an input string is "true" or not. * * RETURN VALUES: 0 or 1, a boolean value for the input string. * * BUGS: Hopefully none. * ==================================================================== */ char string_truth(char *input) { if (input == NULL) { return 0; } while (*input) { if (*input++ != '0') { return 1; } } return 0; } /* ==================================================================== * NAME: dump_context * * DESCRIPTION: Dumps all of the data from a given context into the * namespace of another context. * * RETURN VALUES: None. * * BUGS: Hopefully none. * ==================================================================== */ void dump_context(context_p ctx, context_p dump_ctx, int number) { varlist_p current_var = dump_ctx->variables; nclist_p current_nc = dump_ctx->named_child_contexts; char *number_s; char *var_loop_name; char *nc_loop_name; int size; size = (number / 10) + 1; number_s = (char *)malloc(size + 1); snprintf(number_s, size + 1, "%d", number); number_s[size] = '\0'; size = strlen(number_s) + strlen("variables-"); var_loop_name = (char *)malloc(size + 1); snprintf(var_loop_name, size + 1, "variables-%s", number_s); var_loop_name[size] = '\0'; size = strlen(number_s) + strlen("named_children-"); nc_loop_name = (char *)malloc(size + 1); snprintf(nc_loop_name, size + 1, "named_children-%s", number_s); nc_loop_name[size] = '\0'; template_set_value(ctx, "number", number_s); /* dump variables into a "variables" loop */ while ((current_var != NULL) && (current_var->name != NULL)) { context_p iteration; if ((strcmp(current_var->name, TMPL_VARNAME_OTAG) == 0) || (strcmp(current_var->name, TMPL_VARNAME_DIR) == 0) || (strcmp(current_var->name, TMPL_VARNAME_CTAG) == 0)) { current_var = current_var->next; continue; } iteration = template_loop_iteration(ctx, var_loop_name); template_set_value(iteration, "variable_name", current_var->name); template_set_value(iteration, "variable_value", current_var->value); current_var = current_var->next; } /* dump loops into a "named_children" loop */ while ((current_nc != NULL) && (current_nc->context != NULL)) { context_p iteration = template_loop_iteration(ctx, nc_loop_name); template_set_value(iteration, "nc_name", current_nc->name); context_set_named_child(iteration, current_nc->name); dump_context(context_get_named_child(iteration, current_nc->name), current_nc->context, number + 1); current_nc = current_nc->next; } /* if this is a loop, add an iteration to the ouput context and dump * into it */ if (dump_ctx->next_context != NULL) { dump_context(context_add_peer(ctx), dump_ctx->next_context, number + 1); } free(number_s); free(var_loop_name); free(nc_loop_name); return; }