Mercurial > projects > pwm
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); |