File:  [ELWIX - Embedded LightWeight unIX -] / embedaddon / libpdel / tmpl / test / main.c
Revision 1.1.1.1 (vendor branch): download - view: text, annotated - select for diffs - revision graph
Tue Feb 21 23:25:53 2012 UTC (13 years, 1 month ago) by misho
Branches: libpdel, MAIN
CVS tags: v0_5_3, HEAD
libpdel

    1: 
    2: /*
    3:  * Copyright (c) 2001-2002 Packet Design, LLC.
    4:  * All rights reserved.
    5:  * 
    6:  * Subject to the following obligations and disclaimer of warranty,
    7:  * use and redistribution of this software, in source or object code
    8:  * forms, with or without modifications are expressly permitted by
    9:  * Packet Design; provided, however, that:
   10:  * 
   11:  *    (i)  Any and all reproductions of the source or object code
   12:  *         must include the copyright notice above and the following
   13:  *         disclaimer of warranties; and
   14:  *    (ii) No rights are granted, in any manner or form, to use
   15:  *         Packet Design trademarks, including the mark "PACKET DESIGN"
   16:  *         on advertising, endorsements, or otherwise except as such
   17:  *         appears in the above copyright notice or in the software.
   18:  * 
   19:  * THIS SOFTWARE IS BEING PROVIDED BY PACKET DESIGN "AS IS", AND
   20:  * TO THE MAXIMUM EXTENT PERMITTED BY LAW, PACKET DESIGN MAKES NO
   21:  * REPRESENTATIONS OR WARRANTIES, EXPRESS OR IMPLIED, REGARDING
   22:  * THIS SOFTWARE, INCLUDING WITHOUT LIMITATION, ANY AND ALL IMPLIED
   23:  * WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE,
   24:  * OR NON-INFRINGEMENT.  PACKET DESIGN DOES NOT WARRANT, GUARANTEE,
   25:  * OR MAKE ANY REPRESENTATIONS REGARDING THE USE OF, OR THE RESULTS
   26:  * OF THE USE OF THIS SOFTWARE IN TERMS OF ITS CORRECTNESS, ACCURACY,
   27:  * RELIABILITY OR OTHERWISE.  IN NO EVENT SHALL PACKET DESIGN BE
   28:  * LIABLE FOR ANY DAMAGES RESULTING FROM OR ARISING OUT OF ANY USE
   29:  * OF THIS SOFTWARE, INCLUDING WITHOUT LIMITATION, ANY DIRECT,
   30:  * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, PUNITIVE, OR CONSEQUENTIAL
   31:  * DAMAGES, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, LOSS OF
   32:  * USE, DATA OR PROFITS, HOWEVER CAUSED AND UNDER ANY THEORY OF
   33:  * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
   34:  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
   35:  * THE USE OF THIS SOFTWARE, EVEN IF PACKET DESIGN IS ADVISED OF
   36:  * THE POSSIBILITY OF SUCH DAMAGE.
   37:  *
   38:  * Author: Archie Cobbs <archie@freebsd.org>
   39:  */
   40: 
   41: #include <stdio.h>
   42: #include <stdlib.h>
   43: #include <unistd.h>
   44: #include <string.h>
   45: #include <signal.h>
   46: #include <stdarg.h>
   47: #include <termios.h>
   48: #include <limits.h>
   49: #include <errno.h>
   50: #include <err.h>
   51: 
   52: #include <pdel/structs/structs.h>
   53: #include <pdel/structs/type/array.h>
   54: #include <pdel/tmpl/tmpl.h>
   55: #include <pdel/util/typed_mem.h>
   56: 
   57: #define TMPL_MEM_TYPE	"tmpl_test.tmpl"
   58: #define CTX_MEM_TYPE	"tmpl_test.ctx"
   59: 
   60: #define EOF_STRING	"<<EOF>>"
   61: 
   62: #ifndef TCSASOFT
   63: #define TCSASOFT	0
   64: #endif
   65: 
   66: struct private_info {
   67: 	FILE	*input;
   68: };
   69: 
   70: /*
   71:  * Internal functions
   72:  */
   73: static tmpl_handler_t	readfile_func;
   74: static tmpl_handler_t	display_func;
   75: static tmpl_handler_t	error_func;
   76: static tmpl_handler_t	input_func;
   77: 
   78: static tmpl_handler_t	handler;
   79: static tmpl_errfmtr_t	errfmtr;
   80: 
   81: /*
   82:  * Internal variables
   83:  */
   84: static struct	tmpl_func function_list[] = {
   85: 	{ "display", 		0, INT_MAX,	display_func	},
   86: 	{ "error_test",		0, INT_MAX,	error_func	},
   87: 	{ "func1", 		0, INT_MAX,	display_func	},
   88: 	{ "func2", 		0, INT_MAX,	display_func	},
   89: 	{ "func3", 		0, INT_MAX,	display_func	},
   90: 	{ "input", 		0, 1,		input_func	},
   91: 	{ "readfile", 		1, 1,		readfile_func	},
   92: };
   93: 
   94: int
   95: main(int ac, char **av)
   96: {
   97: 	int flags = TMPL_SKIP_NL_WHITE;
   98: 	struct private_info priv;
   99: 	struct tmpl_ctx *ctx;
  100: 	struct tmpl *tmpl;
  101: 	int show_stats = 0;
  102: 	int num_errors;
  103: 	char *errmsg;
  104: 	FILE *fp;
  105: 	int ch;
  106: 
  107: 	/* Parse command line arguments */
  108: 	while ((ch = getopt(ac, av, "ns")) != -1) {
  109: 		switch (ch) {
  110: 		case 'n':
  111: 			flags &= ~TMPL_SKIP_NL_WHITE;
  112: 			break;
  113: 		case 's':
  114: 			show_stats = 1;
  115: 			break;
  116: 		default:
  117: 			goto usage;
  118: 		}
  119: 	}
  120: 	ac -= optind;
  121: 	av += optind;
  122: 
  123: 	if (ac < 1)
  124: usage:		errx(1, "usage: tmpl [-n] filename [ func arg1 arg2 ...]");
  125: 
  126: 	/* Enable typed memory */
  127: 	if (typed_mem_enable() == -1)
  128: 		err(1, "typed_mem_enable");
  129: 
  130: 	/* Read input file to create template */
  131: 	if ((fp = fopen(av[0], "r")) == NULL)
  132: 		err(1, "%s", av[0]);
  133: 	if ((tmpl = tmpl_create(fp, &num_errors, TMPL_MEM_TYPE)) == NULL)
  134: 		err(1, "tmpl_create: %s", av[0]);
  135: 	fclose(fp);
  136: 	if (num_errors != 0)
  137: 		fprintf(stderr, "There were %d parse errors.\n", num_errors);
  138: 
  139: 	/* Create template context */
  140: 	memset(&priv, 0, sizeof(priv));
  141: 	priv.input = stdin;
  142: 	if ((ctx = tmpl_ctx_create(&priv,
  143: 	    CTX_MEM_TYPE, handler, errfmtr)) == NULL)
  144: 		err(1, "tmpl_ctx_create");
  145: 
  146: 	/* Execute template */
  147: 	if (tmpl_execute(tmpl, ctx, stdout, flags) == -1)
  148: 		err(1, "tmpl_execute");
  149: 
  150: 	/* Execute user defined function */
  151: 	ac--;
  152: 	av++;
  153: 	if (ac > 0 && tmpl_execute_func(ctx,
  154: 	    stdout, &errmsg, ac, av, 0) == -1) {
  155: 		errx(1, "tmpl_execute_func: %s",
  156: 		    errmsg ? errmsg : strerror(errno));
  157: 	}
  158: 
  159: 	/* Free template and context */
  160: 	tmpl_ctx_destroy(&ctx);
  161: 	tmpl_destroy(&tmpl);
  162: 
  163: 	/* Done */
  164: 	if (show_stats)
  165: 		typed_mem_dump(stderr);
  166: 	return (0);
  167: }
  168: 
  169: static char *
  170: handler(struct tmpl_ctx *ctx, char **errmsgp, int ac, char **av)
  171: {
  172: 	return (tmpl_list_handler(ctx, function_list,
  173: 	    sizeof(function_list) / sizeof(*function_list), errmsgp, ac, av));
  174: }
  175: 
  176: static char *
  177: errfmtr(struct tmpl_ctx *ctx, const char *errmsg)
  178: {
  179: 	const char *const mtype = tmpl_ctx_get_mtype(ctx);
  180: 	char *string;
  181: 
  182: 	ASPRINTF(mtype, &string, "[ ERROR: %s ]", errmsg);
  183: 	return (string);
  184: }
  185: 
  186: static char *
  187: error_func(struct tmpl_ctx *ctx, char **errmsgp, int ac, char **av)
  188: {
  189: 	const char *const mtype = tmpl_ctx_get_mtype(ctx);
  190: 
  191: 	*errmsgp = STRDUP(mtype, "Sample error message here");
  192: 	return (NULL);
  193: }
  194: 
  195: static char *
  196: display_func(struct tmpl_ctx *ctx, char **errmsgp, int ac, char **av)
  197: {
  198: 	const char *const mtype = tmpl_ctx_get_mtype(ctx);
  199: 	char buf[1024];
  200: 	int i;
  201: 
  202: 	/* Normal handler output */
  203: 	snprintf(buf, sizeof(buf), "[ %s(", av[0]);
  204: 	for (i = 1; i < ac; i++) {
  205: 		snprintf(buf + strlen(buf), sizeof(buf) - strlen(buf),
  206: 		    "%s%s", av[i], (i == ac - 1) ? "" : ", ");
  207: 	}
  208: 	snprintf(buf + strlen(buf), sizeof(buf) - strlen(buf), ") ]");
  209: 	return (STRDUP(mtype, buf));
  210: }
  211: 
  212: static char *
  213: readfile_func(struct tmpl_ctx *ctx, char **errmsgp, int ac, char **av)
  214: {
  215: 	const char *const mtype = tmpl_ctx_get_mtype(ctx);
  216: 	int errno_save;
  217: 	char *s, *t;
  218: 	FILE *fp;
  219: 	int slen;
  220: 	int nr;
  221: 
  222: 	/* Read file into memory */
  223: 	if ((fp = fopen(av[1], "r")) == NULL)
  224: 		return (NULL);
  225: 	for (s = NULL, slen = 0; 1; slen += nr) {
  226: 		if ((t = REALLOC(mtype, s, slen + 1024)) == NULL) {
  227: 			errno_save = errno;
  228: 			FREE(mtype, s);
  229: 			s = NULL;
  230: 			errno = errno_save;
  231: 			break;
  232: 		}
  233: 		s = t;
  234: 		if ((nr = fread(s + slen, 1, 1024, fp)) == 0) {
  235: 			s[slen] = '\0';
  236: 			break;
  237: 		}
  238: 	}
  239: 
  240: 	/* Close file and return string */
  241: 	errno_save = errno;
  242: 	fclose(fp);
  243: 	errno = errno_save;
  244: 	return (s);
  245: }
  246: 
  247: /*
  248:  * @input()
  249:  *
  250:  * Reads one line of input from the input stream and returns it.
  251:  * If an optional first argument is supplied and its numeric value
  252:  * is non-zero, then the input is assumed to be a terminal device
  253:  * and echo will be disabled (useful for inputting passwords).
  254:  *
  255:  * If no input stream was provided, or EOF is detected, an empty
  256:  * string is returned and "input_eof" is set to "1" (otherwise it
  257:  * will be set to "0").
  258:  */
  259: static char *
  260: input_func(struct tmpl_ctx *ctx, char **errmsgp, int ac, char **av)
  261: {
  262: 	const struct private_info *const priv = tmpl_ctx_get_arg(ctx);
  263: 	const char *const mtype = tmpl_ctx_get_mtype(ctx);
  264: 	int quiet = (ac > 1 && strtol(av[1], NULL, 0) != 0);
  265: 	struct termios term, oterm;
  266: 	char *rtn = NULL;
  267: 	char buf[1024];
  268: 
  269: 	/* If no input supplied, act as if EOF */
  270: 	if (priv->input == NULL) {
  271: 		quiet = 0;
  272: 		if (tmpl_ctx_set_var(ctx, "input_eof", "1"))
  273: 			goto fail;
  274: 		rtn = STRDUP(mtype, "");
  275: 		goto fail;
  276: 	}
  277: 
  278: 	/* Turn echo off if requested */
  279: 	if (quiet) {
  280: 	        if (tcgetattr(fileno(priv->input), &oterm) == -1)
  281: 			quiet = 0;
  282: 		else {
  283: 			term = oterm;
  284: 			term.c_lflag &= ~(ECHO|ECHOE|ECHOK|ECHOKE);
  285: 			if (tcsetattr(fileno(priv->input),
  286: 			    TCSADRAIN|TCSASOFT, &term) == -1)
  287: 				quiet = 0;
  288: 		}
  289: 	}
  290: 
  291: 	/* Read one line of input */
  292: 	if (tmpl_ctx_set_var(ctx, "input_eof", "0"))
  293: 		goto fail;
  294: 	if (fgets(buf, sizeof(buf), priv->input) == NULL) {
  295: 		if (ferror(priv->input))
  296: 			goto fail;
  297: 		if (tmpl_ctx_set_var(ctx, "input_eof", "1"))
  298: 			goto fail;
  299: 		rtn = STRDUP(mtype, "");
  300: 		goto fail;
  301: 	}
  302: 
  303: 	/* Trim trailing newline */
  304: 	if (buf[strlen(buf) - 1] == '\n')
  305: 		buf[strlen(buf) - 1] = '\0';
  306: 
  307: 	/* Copy it to use the right memory type */
  308: 	if ((rtn = STRDUP(mtype, buf)) == NULL)
  309: 		goto fail;
  310: 
  311: fail:
  312: 	/* Clean up and return */
  313: 	if (quiet)
  314: 	        tcsetattr(fileno(priv->input), TCSADRAIN|TCSASOFT, &oterm);
  315: 	return (rtn);
  316: }
  317: 

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>