Return to main.c CVS log | Up to [ELWIX - Embedded LightWeight unIX -] / embedaddon / libpdel / tmpl / test |
1.1 ! misho 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: