Annotation of embedaddon/libpdel/tmpl/test/main.c, revision 1.1

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: 

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