Annotation of embedaddon/libpdel/tmpl/test/main.c, revision 1.1.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>