summaryrefslogtreecommitdiff
path: root/usr.bin
diff options
context:
space:
mode:
authorOtto Moerbeek <otto@cvs.openbsd.org>2003-11-11 09:15:37 +0000
committerOtto Moerbeek <otto@cvs.openbsd.org>2003-11-11 09:15:37 +0000
commitd25ee65f70270070f1919f9470ef34d78d75bf05 (patch)
tree532baae229f86c3acf2e0de4b414e8d5efd0dc3b /usr.bin
parentf34ea382ef91c460ba3d9be0be8e1e0aecb1c839 (diff)
Implement `print' statement, a non-portable extension.
Diffstat (limited to 'usr.bin')
-rw-r--r--usr.bin/bc/bc.y87
-rw-r--r--usr.bin/bc/scan.l5
2 files changed, 87 insertions, 5 deletions
diff --git a/usr.bin/bc/bc.y b/usr.bin/bc/bc.y
index 7db4a3c64b9..992d200e4e6 100644
--- a/usr.bin/bc/bc.y
+++ b/usr.bin/bc/bc.y
@@ -1,5 +1,5 @@
%{
-/* $OpenBSD: bc.y,v 1.14 2003/10/22 12:24:41 otto Exp $ */
+/* $OpenBSD: bc.y,v 1.15 2003/11/11 09:15:36 otto Exp $ */
/*
* Copyright (c) 2003, Otto Moerbeek <otto@drijf.net>
@@ -31,7 +31,7 @@
*/
#ifndef lint
-static const char rcsid[] = "$OpenBSD: bc.y,v 1.14 2003/10/22 12:24:41 otto Exp $";
+static const char rcsid[] = "$OpenBSD: bc.y,v 1.15 2003/11/11 09:15:36 otto Exp $";
#endif /* not lint */
#include <ctype.h>
@@ -74,6 +74,7 @@ static void add_local(ssize_t);
static void warning(const char *);
static void init(void);
static __dead void usage(void);
+static char *escape(const char *);
static size_t instr_sz = 0;
static struct tree *instructions = NULL;
@@ -120,7 +121,7 @@ extern char *__progname;
%token DEFINE BREAK QUIT LENGTH
%token RETURN FOR IF WHILE SQRT
%token SCALE IBASE OBASE AUTO
-%token CONTINUE ELSE
+%token CONTINUE ELSE PRINT
%nonassoc EQUALS LESS_EQ GREATER_EQ UNEQUALS LESS GREATER
%right <str> ASSIGN_OP
@@ -141,6 +142,8 @@ extern char *__progname;
%type <node> opt_expression
%type <node> opt_relational_expression
%type <node> opt_statement
+%type <node> print_expression
+%type <node> print_expression_list
%type <node> relational_expression
%type <node> return_expression
%type <node> semicolon_list
@@ -327,6 +330,10 @@ statement : expression
{
$$ = $2;
}
+ | PRINT print_expression_list
+ {
+ $$ = $2;
+ }
;
alloc_macro : /* empty */
@@ -638,6 +645,26 @@ named_expression
$$.store = cs("o");
}
;
+
+print_expression_list
+ : print_expression
+ | print_expression_list COMMA print_expression
+ {
+ $$ = node($1, $3, END_NODE);
+ }
+
+print_expression
+ : expression
+ {
+ $$ = node($1, cs("dds.n"), END_NODE);
+ }
+ | STRING
+ {
+ char *p = escape($1);
+ $$ = node(cs("["), as(p), cs("]dn"),
+ END_NODE);
+ free(p);
+ }
%%
@@ -834,6 +861,60 @@ usage(void)
exit(1);
}
+static char *
+escape(const char *str)
+{
+ char *ret, *p;
+
+ ret = malloc(strlen(str) + 1);
+ if (ret == NULL)
+ err(1, NULL);
+
+ p = ret;
+ while (*str != '\0') {
+ /*
+ * We get _escaped_ strings here. Single backslashes are
+ * already converted to double backslashes
+ */
+ if (*str == '\\') {
+ if (*++str == '\\') {
+ switch (*++str) {
+ case 'a':
+ *p++ = '\a';
+ break;
+ case 'b':
+ *p++ = '\b';
+ break;
+ case 'f':
+ *p++ = '\f';
+ break;
+ case 'n':
+ *p++ = '\n';
+ break;
+ case 'q':
+ *p++ = '"';
+ break;
+ case 'r':
+ *p++ = '\r';
+ break;
+ case 't':
+ *p++ = '\t';
+ break;
+ case '\\':
+ *p++ = '\\';
+ break;
+ }
+ str++;
+ } else {
+ *p++ = '\\';
+ *p++ = *str++;
+ }
+ } else
+ *p++ = *str++;
+ }
+ *p = '\0';
+ return ret;
+}
int
main(int argc, char *argv[])
diff --git a/usr.bin/bc/scan.l b/usr.bin/bc/scan.l
index 1a4fd2a8957..d6de138c6f3 100644
--- a/usr.bin/bc/scan.l
+++ b/usr.bin/bc/scan.l
@@ -1,5 +1,5 @@
%{
-/* $OpenBSD: scan.l,v 1.10 2003/11/09 19:27:27 otto Exp $ */
+/* $OpenBSD: scan.l,v 1.11 2003/11/11 09:15:36 otto Exp $ */
/*
* Copyright (c) 2003, Otto Moerbeek <otto@drijf.net>
@@ -18,7 +18,7 @@
*/
#ifndef lint
-static const char rcsid[] = "$OpenBSD: scan.l,v 1.10 2003/11/09 19:27:27 otto Exp $";
+static const char rcsid[] = "$OpenBSD: scan.l,v 1.11 2003/11/11 09:15:36 otto Exp $";
#endif /* not lint */
#include <err.h>
@@ -113,6 +113,7 @@ DIGIT [0-9A-F]
"for" return FOR;
"length" return LENGTH;
"obase" return OBASE;
+"print" return PRINT;
"quit" return QUIT;
"return" return RETURN;
"scale" return SCALE;