Mercurial > projects > pwm
comparison cmd.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 |
---|---|
35 #include <time.h> | 35 #include <time.h> |
36 #include <unistd.h> | 36 #include <unistd.h> |
37 | 37 |
38 #include "cmd.h" | 38 #include "cmd.h" |
39 #include "io.h" | 39 #include "io.h" |
40 #include "macro.h" | |
40 #include "pager.h" | 41 #include "pager.h" |
41 #include "proc.h" | 42 #include "proc.h" |
42 #include "pw.h" | 43 #include "pw.h" |
43 #include "pwfile.h" | 44 #include "pwfile.h" |
45 #include "tok.h" | |
44 #include "util.h" | 46 #include "util.h" |
45 | 47 |
46 #define TIME_FORMAT "%Y-%m-%dT%TZ" | 48 #define TIME_FORMAT "%Y-%m-%dT%TZ" |
47 #define TIME_SIZE (4 + 1 + 2 + 1 + 2 + 1 + 8 + 1 + 1) | 49 #define TIME_SIZE (4 + 1 + 2 + 1 + 2 + 1 + 8 + 1 + 1) |
48 | 50 |
80 CHARCLASS_ALNUM, | 82 CHARCLASS_ALNUM, |
81 CHARCLASS_XDIGIT, | 83 CHARCLASS_XDIGIT, |
82 CHARCLASS_GRAPH | 84 CHARCLASS_GRAPH |
83 }; | 85 }; |
84 | 86 |
87 static enum cmd_return cmd_define(struct pwm_ctx *, int, char *[]); | |
85 static enum cmd_return cmd_status(struct pwm_ctx *, int, char *[]); | 88 static enum cmd_return cmd_status(struct pwm_ctx *, int, char *[]); |
86 static enum cmd_return cmd_info(struct pwm_ctx *, int, char *[]); | 89 static enum cmd_return cmd_info(struct pwm_ctx *, int, char *[]); |
87 static enum cmd_return cmd_list(struct pwm_ctx *, int, char *[]); | 90 static enum cmd_return cmd_list(struct pwm_ctx *, int, char *[]); |
88 static enum cmd_return cmd_create(struct pwm_ctx *, int, char *[]); | 91 static enum cmd_return cmd_create(struct pwm_ctx *, int, char *[]); |
89 static enum cmd_return cmd_modify(struct pwm_ctx *, int, char *[]); | 92 static enum cmd_return cmd_modify(struct pwm_ctx *, int, char *[]); |
150 CHARS_DIGIT "abcdef", | 153 CHARS_DIGIT "abcdef", |
151 CHARS_DIGIT CHARS_UPPER CHARS_LOWER CHARS_PUNCT | 154 CHARS_DIGIT CHARS_UPPER CHARS_LOWER CHARS_PUNCT |
152 }; | 155 }; |
153 | 156 |
154 static struct cmd cmds[] = { | 157 static struct cmd cmds[] = { |
158 { "D", "define", "define name=value", "Define a macro", cmd_define }, | |
155 { "t", "status", "status", "Redisplay an error message of the previous " | 159 { "t", "status", "status", "Redisplay an error message of the previous " |
156 "command and unsaved changes", cmd_status }, | 160 "command and unsaved changes", cmd_status }, |
157 { "i", "info", "info", "Show metadata information about the current file", | 161 { "i", "info", "info", "Show metadata information about the current file", |
158 cmd_info }, | 162 cmd_info }, |
159 { "ls", "list", "list [field~regex ...]", "List entries", cmd_list }, | 163 { "ls", "list", "list [field~regex ...]", "List entries", cmd_list }, |
215 | 219 |
216 return (0); | 220 return (0); |
217 } | 221 } |
218 | 222 |
219 static enum cmd_return | 223 static enum cmd_return |
224 cmd_define(struct pwm_ctx *ctx, int argc, char *argv[]) | |
225 { | |
226 int retval = CMD_ERR; | |
227 const char *value; | |
228 char *name = NULL; | |
229 size_t tokenc = 0; | |
230 union tok **tokenv = NULL; | |
231 struct macro_entry *macro_entry; | |
232 | |
233 if (argc != 2) { | |
234 return (CMD_USAGE); | |
235 } | |
236 | |
237 /* split into name and value */ | |
238 value = strchr(argv[1], '='); | |
239 if (value == NULL) { | |
240 pwm_err(ctx, "bad macro definition \"%s\"", argv[1]); | |
241 goto out; | |
242 } | |
243 xasprintf(&name, "%.*s", value - argv[1], argv[1]); | |
244 value++; | |
245 | |
246 /* tokenize macro value */ | |
247 switch (tok_tokenize(value, &tokenc, &tokenv)) { | |
248 case TOK_ERR_UNTERMINATED_QUOTE: | |
249 pwm_err(ctx, "unterminated quote in macro"); | |
250 goto out; | |
251 case TOK_ERR_TRAILING_BACKSLASH: | |
252 pwm_err(ctx, "trailing backslash in macro"); | |
253 goto out; | |
254 case TOK_ERR_INVALID_MACRO_NAME: | |
255 pwm_err(ctx, "invalid macro name referenced in macro"); | |
256 goto out; | |
257 } | |
258 | |
259 /* parse macro definition */ | |
260 switch (macro_parse(name, tokenc, tokenv, ctx->macro_head, | |
261 ¯o_entry)) { | |
262 case MACRO_ERR_INVALID_NAME: | |
263 pwm_err(ctx, "invalid macro name \"%s\"", name); | |
264 goto out; | |
265 case MACRO_ERR_UNDEFINED_MACRO: | |
266 pwm_err(ctx, "macro definition references undefined macro"); | |
267 goto out; | |
268 case MACRO_ERR_RECURSIVE: | |
269 pwm_err(ctx, "macro definition must not be recursive"); | |
270 goto out; | |
271 } | |
272 | |
273 macro_add(ctx->macro_head, macro_entry); | |
274 retval = CMD_OK; | |
275 | |
276 out: | |
277 tok_free(tokenv); | |
278 free(name); | |
279 | |
280 return (retval); | |
281 } | |
282 | |
283 static enum cmd_return | |
220 cmd_status(struct pwm_ctx *ctx, int argc, char *argv[]) | 284 cmd_status(struct pwm_ctx *ctx, int argc, char *argv[]) |
221 { | 285 { |
222 if (argc != 1) { | 286 if (argc != 1) { |
223 return (CMD_USAGE); | 287 return (CMD_USAGE); |
224 } | 288 } |