=================================================================== RCS file: /cvsrepo/anoncvs/cvs/src/usr.bin/bc/bc.y,v retrieving revision 1.14 retrieving revision 1.15 diff -c -r1.14 -r1.15 *** src/usr.bin/bc/bc.y 2003/10/22 12:24:41 1.14 --- src/usr.bin/bc/bc.y 2003/11/11 09:15:36 1.15 *************** *** 1,5 **** %{ ! /* $OpenBSD: bc.y,v 1.14 2003/10/22 12:24:41 otto Exp $ */ /* * Copyright (c) 2003, Otto Moerbeek --- 1,5 ---- %{ ! /* $OpenBSD: bc.y,v 1.15 2003/11/11 09:15:36 otto Exp $ */ /* * Copyright (c) 2003, Otto Moerbeek *************** *** 31,37 **** */ #ifndef lint ! static const char rcsid[] = "$OpenBSD: bc.y,v 1.14 2003/10/22 12:24:41 otto Exp $"; #endif /* not lint */ #include --- 31,37 ---- */ #ifndef lint ! static const char rcsid[] = "$OpenBSD: bc.y,v 1.15 2003/11/11 09:15:36 otto Exp $"; #endif /* not lint */ #include *************** *** 74,79 **** --- 74,80 ---- 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,126 **** %token DEFINE BREAK QUIT LENGTH %token RETURN FOR IF WHILE SQRT %token SCALE IBASE OBASE AUTO ! %token CONTINUE ELSE %nonassoc EQUALS LESS_EQ GREATER_EQ UNEQUALS LESS GREATER %right ASSIGN_OP --- 121,127 ---- %token DEFINE BREAK QUIT LENGTH %token RETURN FOR IF WHILE SQRT %token SCALE IBASE OBASE AUTO ! %token CONTINUE ELSE PRINT %nonassoc EQUALS LESS_EQ GREATER_EQ UNEQUALS LESS GREATER %right ASSIGN_OP *************** *** 141,146 **** --- 142,149 ---- %type opt_expression %type opt_relational_expression %type opt_statement + %type print_expression + %type print_expression_list %type relational_expression %type return_expression %type semicolon_list *************** *** 327,332 **** --- 330,339 ---- { $$ = $2; } + | PRINT print_expression_list + { + $$ = $2; + } ; alloc_macro : /* empty */ *************** *** 638,643 **** --- 645,670 ---- $$.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,839 **** --- 861,920 ---- 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[])