diff options
author | Otto Moerbeek <otto@cvs.openbsd.org> | 2003-11-11 09:15:37 +0000 |
---|---|---|
committer | Otto Moerbeek <otto@cvs.openbsd.org> | 2003-11-11 09:15:37 +0000 |
commit | d25ee65f70270070f1919f9470ef34d78d75bf05 (patch) | |
tree | 532baae229f86c3acf2e0de4b414e8d5efd0dc3b /usr.bin | |
parent | f34ea382ef91c460ba3d9be0be8e1e0aecb1c839 (diff) |
Implement `print' statement, a non-portable extension.
Diffstat (limited to 'usr.bin')
-rw-r--r-- | usr.bin/bc/bc.y | 87 | ||||
-rw-r--r-- | usr.bin/bc/scan.l | 5 |
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; |