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>