diff 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
line wrap: on
line diff
--- a/pwm.c	Thu Sep 21 09:45:59 2017 +0200
+++ b/pwm.c	Mon Sep 25 21:21:25 2017 +0200
@@ -42,6 +42,7 @@
 #include "pwm.h"
 #include "cmd.h"
 #include "io.h"
+#include "macro.h"
 #include "pwfile.h"
 #include "tok.h"
 #include "util.h"
@@ -108,6 +109,8 @@
 	GetLine		*gl = NULL;
 	char		buf[PWM_LINE_MAX + 1];
 	int		io_retval;
+	size_t		tokenc = 0;
+	union tok	**tokenv = NULL;
 	int		argc = 0;
 	char		**argv = NULL;
 	struct cmd	*cmd;
@@ -159,9 +162,7 @@
 		}
 
 		/* tokenize line */
-		switch (tok_tokenize(buf, &argc, &argv)) {
-		case TOK_ERR_SYSTEM_ERROR:
-			err(1, "tok_tokenize");
+		switch (tok_tokenize(buf, &tokenc, &tokenv)) {
 		case TOK_ERR_UNTERMINATED_QUOTE:
 			fprintf(stderr, "unterminated quote\n");
 			if (!ctx->is_interactive) {
@@ -174,6 +175,22 @@
 				goto out;
 			}
 			goto next;
+		case TOK_ERR_INVALID_MACRO_NAME:
+			fprintf(stderr, "invalid macro name\n");
+			if (!ctx->is_interactive) {
+				goto out;
+			}
+			goto next;
+		}
+
+		/* expand macros */
+		if (macro_expand_macros(ctx->macro_head, tokenc, tokenv, &argc,
+		    &argv) != 0) {
+			fprintf(stderr, "undefined macro\n");
+			if (!ctx->is_interactive) {
+				goto out;
+			}
+			goto next;
 		}
 
 		if (argc == 0) {
@@ -216,6 +233,9 @@
 		free(argv);
 		argc = 0;
 		argv = NULL;
+		tok_free(tokenv);
+		tokenc = 0;
+		tokenv = NULL;
 	}
 
 quit:
@@ -226,6 +246,7 @@
 		free(argv[i]);
 	}
 	free(argv);
+	tok_free(tokenv);
 	del_GetLine(gl);
 
 	return (retval);
@@ -397,6 +418,7 @@
 	}
 
 	pwfile_init(&ctx);
+	macro_init(&ctx.macro_head);
 
 	fp = fopen(ctx.filename, "r");
 	if ((fp == NULL) && (errno != ENOENT)) {
@@ -424,6 +446,7 @@
 	status = (run_input_loop(&ctx) != 0);
 
 out:
+	macro_destroy(ctx.macro_head);
 	pwfile_destroy(&ctx);
 	if (fp != NULL) {
 		fclose(fp);