Mercurial > projects > pwm
diff 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 |
line wrap: on
line diff
--- a/cmd.c Thu Sep 21 09:45:59 2017 +0200 +++ b/cmd.c Mon Sep 25 21:21:25 2017 +0200 @@ -37,10 +37,12 @@ #include "cmd.h" #include "io.h" +#include "macro.h" #include "pager.h" #include "proc.h" #include "pw.h" #include "pwfile.h" +#include "tok.h" #include "util.h" #define TIME_FORMAT "%Y-%m-%dT%TZ" @@ -82,6 +84,7 @@ CHARCLASS_GRAPH }; +static enum cmd_return cmd_define(struct pwm_ctx *, int, char *[]); static enum cmd_return cmd_status(struct pwm_ctx *, int, char *[]); static enum cmd_return cmd_info(struct pwm_ctx *, int, char *[]); static enum cmd_return cmd_list(struct pwm_ctx *, int, char *[]); @@ -152,6 +155,7 @@ }; static struct cmd cmds[] = { + { "D", "define", "define name=value", "Define a macro", cmd_define }, { "t", "status", "status", "Redisplay an error message of the previous " "command and unsaved changes", cmd_status }, { "i", "info", "info", "Show metadata information about the current file", @@ -217,6 +221,66 @@ } static enum cmd_return +cmd_define(struct pwm_ctx *ctx, int argc, char *argv[]) +{ + int retval = CMD_ERR; + const char *value; + char *name = NULL; + size_t tokenc = 0; + union tok **tokenv = NULL; + struct macro_entry *macro_entry; + + if (argc != 2) { + return (CMD_USAGE); + } + + /* split into name and value */ + value = strchr(argv[1], '='); + if (value == NULL) { + pwm_err(ctx, "bad macro definition \"%s\"", argv[1]); + goto out; + } + xasprintf(&name, "%.*s", value - argv[1], argv[1]); + value++; + + /* tokenize macro value */ + switch (tok_tokenize(value, &tokenc, &tokenv)) { + case TOK_ERR_UNTERMINATED_QUOTE: + pwm_err(ctx, "unterminated quote in macro"); + goto out; + case TOK_ERR_TRAILING_BACKSLASH: + pwm_err(ctx, "trailing backslash in macro"); + goto out; + case TOK_ERR_INVALID_MACRO_NAME: + pwm_err(ctx, "invalid macro name referenced in macro"); + goto out; + } + + /* parse macro definition */ + switch (macro_parse(name, tokenc, tokenv, ctx->macro_head, + ¯o_entry)) { + case MACRO_ERR_INVALID_NAME: + pwm_err(ctx, "invalid macro name \"%s\"", name); + goto out; + case MACRO_ERR_UNDEFINED_MACRO: + pwm_err(ctx, "macro definition references undefined macro"); + goto out; + case MACRO_ERR_RECURSIVE: + pwm_err(ctx, "macro definition must not be recursive"); + goto out; + } + + macro_add(ctx->macro_head, macro_entry); + retval = CMD_OK; + +out: + tok_free(tokenv); + free(name); + + return (retval); +} + +static enum cmd_return cmd_status(struct pwm_ctx *ctx, int argc, char *argv[]) { if (argc != 1) {