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 &macro_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 }