comparison pwm.c @ 27:722a45b4028b

Add define command for defining macros Macros are parsed when they are defined with the D command and can subsequently be used as arguments for other commands. Handle out of memory errors directly in tok.c.
author Guido Berhoerster <guido+pwm@berhoerster.name>
date Mon, 25 Sep 2017 21:21:25 +0200
parents 1b89066d992c
children e3db02d7f1f4
comparison
equal deleted inserted replaced
26:5bdea77d0c1d 27:722a45b4028b
40 #include <unistd.h> 40 #include <unistd.h>
41 41
42 #include "pwm.h" 42 #include "pwm.h"
43 #include "cmd.h" 43 #include "cmd.h"
44 #include "io.h" 44 #include "io.h"
45 #include "macro.h"
45 #include "pwfile.h" 46 #include "pwfile.h"
46 #include "tok.h" 47 #include "tok.h"
47 #include "util.h" 48 #include "util.h"
48 49
49 static void 50 static void
106 int retval = -1; 107 int retval = -1;
107 char prompt[8 + 2 + 1]; 108 char prompt[8 + 2 + 1];
108 GetLine *gl = NULL; 109 GetLine *gl = NULL;
109 char buf[PWM_LINE_MAX + 1]; 110 char buf[PWM_LINE_MAX + 1];
110 int io_retval; 111 int io_retval;
112 size_t tokenc = 0;
113 union tok **tokenv = NULL;
111 int argc = 0; 114 int argc = 0;
112 char **argv = NULL; 115 char **argv = NULL;
113 struct cmd *cmd; 116 struct cmd *cmd;
114 int i; 117 int i;
115 118
157 fprintf(stderr, "unknown error\n"); 160 fprintf(stderr, "unknown error\n");
158 goto quit; 161 goto quit;
159 } 162 }
160 163
161 /* tokenize line */ 164 /* tokenize line */
162 switch (tok_tokenize(buf, &argc, &argv)) { 165 switch (tok_tokenize(buf, &tokenc, &tokenv)) {
163 case TOK_ERR_SYSTEM_ERROR:
164 err(1, "tok_tokenize");
165 case TOK_ERR_UNTERMINATED_QUOTE: 166 case TOK_ERR_UNTERMINATED_QUOTE:
166 fprintf(stderr, "unterminated quote\n"); 167 fprintf(stderr, "unterminated quote\n");
167 if (!ctx->is_interactive) { 168 if (!ctx->is_interactive) {
168 goto out; 169 goto out;
169 } 170 }
170 goto next; 171 goto next;
171 case TOK_ERR_TRAILING_BACKSLASH: 172 case TOK_ERR_TRAILING_BACKSLASH:
172 fprintf(stderr, "trailing backslash\n"); 173 fprintf(stderr, "trailing backslash\n");
174 if (!ctx->is_interactive) {
175 goto out;
176 }
177 goto next;
178 case TOK_ERR_INVALID_MACRO_NAME:
179 fprintf(stderr, "invalid macro name\n");
180 if (!ctx->is_interactive) {
181 goto out;
182 }
183 goto next;
184 }
185
186 /* expand macros */
187 if (macro_expand_macros(ctx->macro_head, tokenc, tokenv, &argc,
188 &argv) != 0) {
189 fprintf(stderr, "undefined macro\n");
173 if (!ctx->is_interactive) { 190 if (!ctx->is_interactive) {
174 goto out; 191 goto out;
175 } 192 }
176 goto next; 193 goto next;
177 } 194 }
214 free(argv[i]); 231 free(argv[i]);
215 } 232 }
216 free(argv); 233 free(argv);
217 argc = 0; 234 argc = 0;
218 argv = NULL; 235 argv = NULL;
236 tok_free(tokenv);
237 tokenc = 0;
238 tokenv = NULL;
219 } 239 }
220 240
221 quit: 241 quit:
222 retval = 0; 242 retval = 0;
223 243
224 out: 244 out:
225 for (i = 0; i < argc; i++) { 245 for (i = 0; i < argc; i++) {
226 free(argv[i]); 246 free(argv[i]);
227 } 247 }
228 free(argv); 248 free(argv);
249 tok_free(tokenv);
229 del_GetLine(gl); 250 del_GetLine(gl);
230 251
231 return (retval); 252 return (retval);
232 } 253 }
233 254
395 "running non-interactively\n"); 416 "running non-interactively\n");
396 goto out; 417 goto out;
397 } 418 }
398 419
399 pwfile_init(&ctx); 420 pwfile_init(&ctx);
421 macro_init(&ctx.macro_head);
400 422
401 fp = fopen(ctx.filename, "r"); 423 fp = fopen(ctx.filename, "r");
402 if ((fp == NULL) && (errno != ENOENT)) { 424 if ((fp == NULL) && (errno != ENOENT)) {
403 warn("failed to open password database"); 425 warn("failed to open password database");
404 goto out; 426 goto out;
422 444
423 /* run main input loop */ 445 /* run main input loop */
424 status = (run_input_loop(&ctx) != 0); 446 status = (run_input_loop(&ctx) != 0);
425 447
426 out: 448 out:
449 macro_destroy(ctx.macro_head);
427 pwfile_destroy(&ctx); 450 pwfile_destroy(&ctx);
428 if (fp != NULL) { 451 if (fp != NULL) {
429 fclose(fp); 452 fclose(fp);
430 } 453 }
431 free(ctx.filename); 454 free(ctx.filename);