version 1.14, 2003/10/22 12:24:41 |
version 1.15, 2003/11/11 09:15:36 |
|
|
static void warning(const char *); |
static void warning(const char *); |
static void init(void); |
static void init(void); |
static __dead void usage(void); |
static __dead void usage(void); |
|
static char *escape(const char *); |
|
|
static size_t instr_sz = 0; |
static size_t instr_sz = 0; |
static struct tree *instructions = NULL; |
static struct tree *instructions = NULL; |
|
|
%token DEFINE BREAK QUIT LENGTH |
%token DEFINE BREAK QUIT LENGTH |
%token RETURN FOR IF WHILE SQRT |
%token RETURN FOR IF WHILE SQRT |
%token SCALE IBASE OBASE AUTO |
%token SCALE IBASE OBASE AUTO |
%token CONTINUE ELSE |
%token CONTINUE ELSE PRINT |
|
|
%nonassoc EQUALS LESS_EQ GREATER_EQ UNEQUALS LESS GREATER |
%nonassoc EQUALS LESS_EQ GREATER_EQ UNEQUALS LESS GREATER |
%right <str> ASSIGN_OP |
%right <str> ASSIGN_OP |
|
|
%type <node> opt_expression |
%type <node> opt_expression |
%type <node> opt_relational_expression |
%type <node> opt_relational_expression |
%type <node> opt_statement |
%type <node> opt_statement |
|
%type <node> print_expression |
|
%type <node> print_expression_list |
%type <node> relational_expression |
%type <node> relational_expression |
%type <node> return_expression |
%type <node> return_expression |
%type <node> semicolon_list |
%type <node> semicolon_list |
|
|
{ |
{ |
$$ = $2; |
$$ = $2; |
} |
} |
|
| PRINT print_expression_list |
|
{ |
|
$$ = $2; |
|
} |
; |
; |
|
|
alloc_macro : /* empty */ |
alloc_macro : /* empty */ |
|
|
$$.store = cs("o"); |
$$.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); |
|
} |
%% |
%% |
|
|
|
|
|
|
exit(1); |
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 |
int |
main(int argc, char *argv[]) |
main(int argc, char *argv[]) |