Get rid of 'ab'-s, added return to functions.
This commit is contained in:
parent
df0cf75dc8
commit
2d496d2028
4 changed files with 106 additions and 69 deletions
|
@ -6,7 +6,7 @@
|
||||||
* Can be freely distributed and used under the terms of the GNU GPL.
|
* Can be freely distributed and used under the terms of the GNU GPL.
|
||||||
*
|
*
|
||||||
FIXME (nonurgent): define keyword
|
FIXME (nonurgent): define keyword
|
||||||
FIXME: whole system of paths, path ~ string, path.prepend(), path.originate
|
FIXME (for BGP): whole system of paths, path ~ string, path.prepend(), path.originate
|
||||||
FIXME: create community lists
|
FIXME: create community lists
|
||||||
FIXME: '! =' should not be permitted. Ze `!=' by nemelo byt totez jako `! =' Nadefinujes si pres %token novy token a do cf-lex.l pridas nove pravidlo, ktere jej rozpoznava. Napriklad != return NEQ;
|
FIXME: '! =' should not be permitted. Ze `!=' by nemelo byt totez jako `! =' Nadefinujes si pres %token novy token a do cf-lex.l pridas nove pravidlo, ktere jej rozpoznava. Napriklad != return NEQ;
|
||||||
FIXME: IP addresses in ipv6
|
FIXME: IP addresses in ipv6
|
||||||
|
@ -25,9 +25,11 @@ CF_HDR
|
||||||
#include "nest/route.h"
|
#include "nest/route.h"
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
|
||||||
|
#define P(a,b) ((a<<8) | b)
|
||||||
|
|
||||||
CF_DECLS
|
CF_DECLS
|
||||||
|
|
||||||
CF_KEYWORDS(FUNCTION, PRINT, PRINTN, CONST, UNSET,
|
CF_KEYWORDS(FUNCTION, PRINT, PRINTN, CONST, UNSET, RETURN,
|
||||||
ACCEPT, REJECT, ERROR, QUITBIRD,
|
ACCEPT, REJECT, ERROR, QUITBIRD,
|
||||||
INT, BOOL, IP, PREFIX, PAIR, SET, STRING,
|
INT, BOOL, IP, PREFIX, PAIR, SET, STRING,
|
||||||
IF, THEN, ELSE, CASE,
|
IF, THEN, ELSE, CASE,
|
||||||
|
@ -41,7 +43,7 @@ CF_KEYWORDS(FUNCTION, PRINT, PRINTN, CONST, UNSET,
|
||||||
%nonassoc THEN
|
%nonassoc THEN
|
||||||
%nonassoc ELSE
|
%nonassoc ELSE
|
||||||
|
|
||||||
%type <x> term block cmds cmd function_body constant print_one print_list var_list var_listn any_dynamic
|
%type <x> term block cmds cmd function_body constant print_one print_list var_list var_listn any_dynamic function_call
|
||||||
%type <f> filter filter_body where_filter
|
%type <f> filter filter_body where_filter
|
||||||
%type <i> type break_command pair
|
%type <i> type break_command pair
|
||||||
%type <e> set_item set_items switch_body
|
%type <e> set_item set_items switch_body
|
||||||
|
@ -132,11 +134,11 @@ where_filter:
|
||||||
struct filter *f = cfg_alloc(sizeof(struct filter));
|
struct filter *f = cfg_alloc(sizeof(struct filter));
|
||||||
struct f_inst *i, *acc, *rej;
|
struct f_inst *i, *acc, *rej;
|
||||||
acc = f_new_inst(); /* ACCEPT */
|
acc = f_new_inst(); /* ACCEPT */
|
||||||
acc->code = 'p,';
|
acc->code = P('p',',');
|
||||||
acc->a1.p = NULL;
|
acc->a1.p = NULL;
|
||||||
acc->a2.i = F_ACCEPT;
|
acc->a2.i = F_ACCEPT;
|
||||||
rej = f_new_inst(); /* REJECT */
|
rej = f_new_inst(); /* REJECT */
|
||||||
rej->code = 'p,';
|
rej->code = P('p',',');
|
||||||
rej->a1.p = NULL;
|
rej->a1.p = NULL;
|
||||||
rej->a2.i = F_REJECT;
|
rej->a2.i = F_REJECT;
|
||||||
i = f_new_inst(); /* IF */
|
i = f_new_inst(); /* IF */
|
||||||
|
@ -274,17 +276,41 @@ any_dynamic:
|
||||||
rtadot: /* EMPTY, we are not permitted RTA. prefix */
|
rtadot: /* EMPTY, we are not permitted RTA. prefix */
|
||||||
;
|
;
|
||||||
|
|
||||||
|
function_call:
|
||||||
|
SYM '(' var_list ')' {
|
||||||
|
struct symbol *sym;
|
||||||
|
struct f_inst *inst = $3;
|
||||||
|
if ($1->class != SYM_FUNCTION)
|
||||||
|
cf_error("You can not call something which is not function. Really.");
|
||||||
|
printf("You are calling function %s\n", $1->name);
|
||||||
|
$$ = f_new_inst();
|
||||||
|
$$->code = P('c','a');
|
||||||
|
$$->a1.p = inst;
|
||||||
|
$$->a2.p = $1->aux2;
|
||||||
|
sym = (void *) $1->aux;
|
||||||
|
while (sym || inst) {
|
||||||
|
if (!sym || !inst)
|
||||||
|
cf_error("wrong number of arguments for function %s.", $1->name);
|
||||||
|
printf( "You should pass parameter called %s\n", sym->name);
|
||||||
|
inst->a1.p = sym;
|
||||||
|
sym = (void *) sym->aux;
|
||||||
|
inst = inst->next;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
;
|
||||||
|
|
||||||
|
|
||||||
term:
|
term:
|
||||||
'(' term ')' { $$ = $2; }
|
'(' term ')' { $$ = $2; }
|
||||||
| term '+' term { $$ = f_new_inst(); $$->code = '+'; $$->a1.p = $1; $$->a2.p = $3; }
|
| term '+' term { $$ = f_new_inst(); $$->code = '+'; $$->a1.p = $1; $$->a2.p = $3; }
|
||||||
| term '=' term { $$ = f_new_inst(); $$->code = '=='; $$->a1.p = $1; $$->a2.p = $3; }
|
| term '=' term { $$ = f_new_inst(); $$->code = P('=','='); $$->a1.p = $1; $$->a2.p = $3; }
|
||||||
| term '!' '=' term { $$ = f_new_inst(); $$->code = '!='; $$->a1.p = $1; $$->a2.p = $4; }
|
| term '!' '=' term { $$ = f_new_inst(); $$->code = P('!','='); $$->a1.p = $1; $$->a2.p = $4; }
|
||||||
| term '<' term { $$ = f_new_inst(); $$->code = '<'; $$->a1.p = $1; $$->a2.p = $3; }
|
| term '<' term { $$ = f_new_inst(); $$->code = '<'; $$->a1.p = $1; $$->a2.p = $3; }
|
||||||
| term '<' '=' term { $$ = f_new_inst(); $$->code = '<='; $$->a1.p = $1; $$->a2.p = $4; }
|
| term '<' '=' term { $$ = f_new_inst(); $$->code = P('<','='); $$->a1.p = $1; $$->a2.p = $4; }
|
||||||
| term '>' term { $$ = f_new_inst(); $$->code = '<'; $$->a1.p = $3; $$->a2.p = $1; }
|
| term '>' term { $$ = f_new_inst(); $$->code = '<'; $$->a1.p = $3; $$->a2.p = $1; }
|
||||||
| term '>' '=' term { $$ = f_new_inst(); $$->code = '<='; $$->a1.p = $4; $$->a2.p = $1; }
|
| term '>' '=' term { $$ = f_new_inst(); $$->code = P('<','='); $$->a1.p = $4; $$->a2.p = $1; }
|
||||||
| term '~' term { $$ = f_new_inst(); $$->code = '~'; $$->a1.p = $1; $$->a2.p = $3; }
|
| term '~' term { $$ = f_new_inst(); $$->code = '~'; $$->a1.p = $1; $$->a2.p = $3; }
|
||||||
| DEFINED '(' term ')' { $$ = f_new_inst(); $$->code = 'de'; $$->a1.p = $3; }
|
| DEFINED '(' term ')' { $$ = f_new_inst(); $$->code = P('d','e'); $$->a1.p = $3; }
|
||||||
|
|
||||||
| constant { $$ = $1; }
|
| constant { $$ = $1; }
|
||||||
| SYM {
|
| SYM {
|
||||||
|
@ -308,11 +334,12 @@ term:
|
||||||
| rtadot NET { $$ = f_new_inst(); $$->code = 'a'; $$->aux = T_PREFIX; $$->a2.i = 0x12345678; }
|
| rtadot NET { $$ = f_new_inst(); $$->code = 'a'; $$->aux = T_PREFIX; $$->a2.i = 0x12345678; }
|
||||||
| rtadot SOURCE { $$ = f_new_inst(); $$->code = 'a'; $$->aux = T_ENUM_RTS; $$->a2.i = OFFSETOF(struct rta, gw); }
|
| rtadot SOURCE { $$ = f_new_inst(); $$->code = 'a'; $$->aux = T_ENUM_RTS; $$->a2.i = OFFSETOF(struct rta, gw); }
|
||||||
|
|
||||||
| rtadot any_dynamic { $$ = $2; $$->code = 'ea'; }
|
| rtadot any_dynamic { $$ = $2; $$->code = P('e','a'); }
|
||||||
|
|
||||||
| term '.' IP { $$ = f_new_inst(); $$->code = 'cp'; $$->a1.p = $1; $$->aux = T_IP; }
|
| term '.' IP { $$ = f_new_inst(); $$->code = P('c','p'); $$->a1.p = $1; $$->aux = T_IP; }
|
||||||
| term '.' LEN { $$ = f_new_inst(); $$->code = 'cp'; $$->a1.p = $1; $$->aux = T_INT; }
|
| term '.' LEN { $$ = f_new_inst(); $$->code = P('c','p'); $$->a1.p = $1; $$->aux = T_INT; }
|
||||||
| term '.' MASK '(' term ')' { $$ = f_new_inst(); $$->code = 'iM'; $$->a1.p = $1; $$->a2.p = $5; }
|
| term '.' MASK '(' term ')' { $$ = f_new_inst(); $$->code = P('i','M'); $$->a1.p = $1; $$->a2.p = $5; }
|
||||||
|
| function_call { $$ = $1; /* 1 shift/reduce conflict */ }
|
||||||
;
|
;
|
||||||
|
|
||||||
break_command:
|
break_command:
|
||||||
|
@ -383,41 +410,28 @@ cmd:
|
||||||
$$->a1.p = $1;
|
$$->a1.p = $1;
|
||||||
$$->a2.p = $3;
|
$$->a2.p = $3;
|
||||||
}
|
}
|
||||||
|
| RETURN term ';' {
|
||||||
|
$$ = f_new_inst();
|
||||||
|
printf( "Ook, we'll return the value\n" );
|
||||||
|
$$->code = 'r';
|
||||||
|
$$->a1.p = $2;
|
||||||
|
}
|
||||||
| rtadot any_dynamic '=' term ';' {
|
| rtadot any_dynamic '=' term ';' {
|
||||||
$$ = $2;
|
$$ = $2;
|
||||||
$$->code = 'eS';
|
$$->code = P('e','S');
|
||||||
$$->a1.p = $4;
|
$$->a1.p = $4;
|
||||||
}
|
}
|
||||||
| UNSET '(' rtadot any_dynamic ')' ';' {
|
| UNSET '(' rtadot any_dynamic ')' ';' {
|
||||||
$$ = $4;
|
$$ = $4;
|
||||||
$$->aux = T_VOID;
|
$$->aux = T_VOID;
|
||||||
$$->code = 'eS';
|
$$->code = P('e','S');
|
||||||
$$->a1.p = NULL;
|
$$->a1.p = NULL;
|
||||||
}
|
}
|
||||||
| break_command print_list ';' { $$ = f_new_inst(); $$->code = 'p,'; $$->a1.p = $2; $$->a2.i = $1; }
|
| break_command print_list ';' { $$ = f_new_inst(); $$->code = P('p',','); $$->a1.p = $2; $$->a2.i = $1; }
|
||||||
| SYM '(' var_list ')' ';' {
|
| function_call ';' { $$ = $1; }
|
||||||
struct symbol *sym;
|
|
||||||
struct f_inst *inst = $3;
|
|
||||||
if ($1->class != SYM_FUNCTION)
|
|
||||||
cf_error("You can not call something which is not function. Really.");
|
|
||||||
printf("You are calling function %s\n", $1->name);
|
|
||||||
$$ = f_new_inst();
|
|
||||||
$$->code = 'ca';
|
|
||||||
$$->a1.p = inst;
|
|
||||||
$$->a2.p = $1->aux2;
|
|
||||||
sym = (void *) $1->aux;
|
|
||||||
while (sym || inst) {
|
|
||||||
if (!sym || !inst)
|
|
||||||
cf_error("wrong number of arguments for function %s.", $1->name);
|
|
||||||
printf( "You should pass parameter called %s\n", sym->name);
|
|
||||||
inst->a1.p = sym;
|
|
||||||
sym = (void *) sym->aux;
|
|
||||||
inst = inst->next;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
| CASE term '{' switch_body '}' {
|
| CASE term '{' switch_body '}' {
|
||||||
$$ = f_new_inst();
|
$$ = f_new_inst();
|
||||||
$$->code = 'SW';
|
$$->code = P('S','W');
|
||||||
$$->a1.p = $2;
|
$$->a1.p = $2;
|
||||||
$$->a2.p = build_tree( $4 );
|
$$->a2.p = build_tree( $4 );
|
||||||
}
|
}
|
||||||
|
|
|
@ -26,6 +26,8 @@
|
||||||
#include "conf/conf.h"
|
#include "conf/conf.h"
|
||||||
#include "filter/filter.h"
|
#include "filter/filter.h"
|
||||||
|
|
||||||
|
#define P(a,b) ((a<<8) | b)
|
||||||
|
|
||||||
struct f_inst *startup_func = NULL;
|
struct f_inst *startup_func = NULL;
|
||||||
|
|
||||||
#define CMP_ERROR 999
|
#define CMP_ERROR 999
|
||||||
|
@ -150,7 +152,7 @@ static struct linpool *f_pool;
|
||||||
|
|
||||||
#define ARG(x,y) \
|
#define ARG(x,y) \
|
||||||
x = interpret(what->y); \
|
x = interpret(what->y); \
|
||||||
if (x.type == T_RETURN) \
|
if (x.type & T_RETURN) \
|
||||||
return x;
|
return x;
|
||||||
|
|
||||||
#define ONEARG ARG(v1, a1.p)
|
#define ONEARG ARG(v1, a1.p)
|
||||||
|
@ -208,10 +210,10 @@ interpret(struct f_inst *what)
|
||||||
res.val.i = (x); \
|
res.val.i = (x); \
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case '!=': COMPARE(i!=0);
|
case P('!','='): COMPARE(i!=0);
|
||||||
case '==': COMPARE(i==0);
|
case P('=','='): COMPARE(i==0);
|
||||||
case '<': COMPARE(i==-1);
|
case '<': COMPARE(i==-1);
|
||||||
case '<=': COMPARE(i!=1);
|
case P('<','='): COMPARE(i!=1);
|
||||||
|
|
||||||
case '~':
|
case '~':
|
||||||
TWOARGS;
|
TWOARGS;
|
||||||
|
@ -220,7 +222,7 @@ interpret(struct f_inst *what)
|
||||||
if (res.val.i == CMP_ERROR)
|
if (res.val.i == CMP_ERROR)
|
||||||
runtime( "~ applied on unknown type pair" );
|
runtime( "~ applied on unknown type pair" );
|
||||||
break;
|
break;
|
||||||
case 'de':
|
case P('d','e'):
|
||||||
ONEARG;
|
ONEARG;
|
||||||
res.type = T_BOOL;
|
res.type = T_BOOL;
|
||||||
res.val.i = (v1.type != T_VOID);
|
res.val.i = (v1.type != T_VOID);
|
||||||
|
@ -270,7 +272,7 @@ interpret(struct f_inst *what)
|
||||||
case '0':
|
case '0':
|
||||||
printf( "No operation\n" );
|
printf( "No operation\n" );
|
||||||
break;
|
break;
|
||||||
case 'p,':
|
case P('p',','):
|
||||||
ONEARG;
|
ONEARG;
|
||||||
if (what->a2.i != F_NONL)
|
if (what->a2.i != F_NONL)
|
||||||
printf( "\n" );
|
printf( "\n" );
|
||||||
|
@ -314,9 +316,10 @@ interpret(struct f_inst *what)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 'ea': /* Access to extended attributes [hmm, but we need it read/write, do we?] */
|
case P('e','a'): /* Access to extended attributes */
|
||||||
{
|
{
|
||||||
eattr *e = ea_find( (*f_rte)->attrs->eattrs, what->a2.i );
|
eattr *e = ea_find( (*f_rte)->attrs->eattrs, what->a2.i );
|
||||||
|
/* FIXME: should I search in tmp_attrs, too, or what ? */
|
||||||
if (!e) {
|
if (!e) {
|
||||||
res.type = T_VOID;
|
res.type = T_VOID;
|
||||||
break;
|
break;
|
||||||
|
@ -329,7 +332,7 @@ interpret(struct f_inst *what)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 'eS':
|
case P('e','S'):
|
||||||
ONEARG;
|
ONEARG;
|
||||||
if (v1.type != what->aux)
|
if (v1.type != what->aux)
|
||||||
runtime("Wrong type when setting dynamic attribute\n");
|
runtime("Wrong type when setting dynamic attribute\n");
|
||||||
|
@ -358,7 +361,7 @@ interpret(struct f_inst *what)
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 'cp': /* Convert prefix to ... */
|
case P('c','p'): /* Convert prefix to ... */
|
||||||
ONEARG;
|
ONEARG;
|
||||||
if (v1.type != T_PREFIX)
|
if (v1.type != T_PREFIX)
|
||||||
runtime( "Can not convert non-prefix this way" );
|
runtime( "Can not convert non-prefix this way" );
|
||||||
|
@ -369,11 +372,19 @@ interpret(struct f_inst *what)
|
||||||
default: bug( "Unknown prefix to conversion\n" );
|
default: bug( "Unknown prefix to conversion\n" );
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 'ca': /* CALL */
|
case 'r':
|
||||||
|
ONEARG;
|
||||||
|
res = v1;
|
||||||
|
res.type |= T_RETURN;
|
||||||
|
break;
|
||||||
|
case P('c','a'): /* CALL: this is special: if T_RETURN and returning some value, mask it out */
|
||||||
ONEARG;
|
ONEARG;
|
||||||
res = interpret(what->a2.p);
|
res = interpret(what->a2.p);
|
||||||
|
if (res.type == T_RETURN)
|
||||||
|
return res;
|
||||||
|
res.type &= ~T_RETURN;
|
||||||
break;
|
break;
|
||||||
case 'SW':
|
case P('S','W'):
|
||||||
ONEARG;
|
ONEARG;
|
||||||
{
|
{
|
||||||
struct f_tree *t = find_tree(what->a2.p, v1);
|
struct f_tree *t = find_tree(what->a2.p, v1);
|
||||||
|
@ -390,7 +401,7 @@ interpret(struct f_inst *what)
|
||||||
return interpret(t->data);
|
return interpret(t->data);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 'iM': /* IP.MASK(val) */
|
case P('i','M'): /* IP.MASK(val) */
|
||||||
TWOARGS;
|
TWOARGS;
|
||||||
if (v2.type != T_INT)
|
if (v2.type != T_INT)
|
||||||
runtime( "Can not use this type for mask.");
|
runtime( "Can not use this type for mask.");
|
||||||
|
@ -410,6 +421,7 @@ interpret(struct f_inst *what)
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#undef ARG
|
||||||
#define ARG(x,y) \
|
#define ARG(x,y) \
|
||||||
if (!i_same(f1->y, f2->y)) \
|
if (!i_same(f1->y, f2->y)) \
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -436,13 +448,13 @@ i_same(struct f_inst *f1, struct f_inst *f2)
|
||||||
case ',': /* fall through */
|
case ',': /* fall through */
|
||||||
case '+':
|
case '+':
|
||||||
case '/':
|
case '/':
|
||||||
case '!=':
|
case P('!','='):
|
||||||
case '==':
|
case P('=','='):
|
||||||
case '<':
|
case '<':
|
||||||
case '<=': TWOARGS; break;
|
case P('<','='): TWOARGS; break;
|
||||||
|
|
||||||
case '~': TWOARGS; break;
|
case '~': TWOARGS; break;
|
||||||
case 'de': ONEARG; break;
|
case P('d','e'): ONEARG; break;
|
||||||
|
|
||||||
case 's':
|
case 's':
|
||||||
ARG(v2, a2.p);
|
ARG(v2, a2.p);
|
||||||
|
@ -465,23 +477,25 @@ i_same(struct f_inst *f1, struct f_inst *f2)
|
||||||
case 'p': ONEARG; break;
|
case 'p': ONEARG; break;
|
||||||
case '?': TWOARGS; break;
|
case '?': TWOARGS; break;
|
||||||
case '0': break;
|
case '0': break;
|
||||||
case 'p,': ONEARG; A2_SAME; break;
|
case P('p',','): ONEARG; A2_SAME; break;
|
||||||
case 'a': A2_SAME; break;
|
case 'a': A2_SAME; break;
|
||||||
case 'ea': A2_SAME; break;
|
case P('e','a'): A2_SAME; break;
|
||||||
case 'eS': ONEARG; A2_SAME; break;
|
case P('e','S'): ONEARG; A2_SAME; break;
|
||||||
|
|
||||||
case 'cp': ONEARG; break;
|
case 'r': ONEARG; break;
|
||||||
case 'ca': /* CALL, FIXME: exponential in some cases */
|
case P('c','p'): ONEARG; break;
|
||||||
|
case P('c','a'): /* CALL, FIXME: exponential in some cases */
|
||||||
ONEARG; if (!i_same(f1->a2.p, f2->a2.p)) return 0; break;
|
ONEARG; if (!i_same(f1->a2.p, f2->a2.p)) return 0; break;
|
||||||
case 'SW': ONEARG; if (!same_tree(f1->a2.p, f2->a2.p)) return 0; break;
|
case P('S','W'): ONEARG; if (!same_tree(f1->a2.p, f2->a2.p)) return 0; break;
|
||||||
case 'iM': TWOARGS; break;
|
case P('i','M'): TWOARGS; break;
|
||||||
default:
|
default:
|
||||||
bug( "Unknown instruction %d in same (%c)", f1->code, f1->code & 0xff);
|
bug( "Unknown instruction %d in same (%c)", f1->code, f1->code & 0xff);
|
||||||
}
|
}
|
||||||
return i_same(f1->next, f2->next);
|
return i_same(f1->next, f2->next);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* FIXME: tmp_attrs is unreferenced. That can't be right */
|
/* FIXME: tmp_attrs is unreferenced. That can't be right.
|
||||||
|
Strange. look at eS how dynamic attrs are set. */
|
||||||
int
|
int
|
||||||
f_run(struct filter *filter, struct rte **rte, struct ea_list **tmp_attrs, struct linpool *tmp_pool)
|
f_run(struct filter *filter, struct rte **rte, struct ea_list **tmp_attrs, struct linpool *tmp_pool)
|
||||||
{
|
{
|
||||||
|
@ -500,8 +514,6 @@ f_run(struct filter *filter, struct rte **rte, struct ea_list **tmp_attrs, struc
|
||||||
return res.val.i;
|
return res.val.i;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
void
|
void
|
||||||
filters_postconfig(void)
|
filters_postconfig(void)
|
||||||
{
|
{
|
||||||
|
|
|
@ -91,16 +91,15 @@ void val_print(struct f_val v);
|
||||||
/* Internal types */
|
/* Internal types */
|
||||||
/* Do not use type of zero, that way we'll see errors easier. */
|
/* Do not use type of zero, that way we'll see errors easier. */
|
||||||
#define T_VOID 1
|
#define T_VOID 1
|
||||||
#define T_RETURN 2
|
|
||||||
|
|
||||||
/* User visible types, which fit in int */
|
/* User visible types, which fit in int */
|
||||||
#define T_INT 0x10
|
#define T_INT 0x10
|
||||||
#define T_BOOL 0x11
|
#define T_BOOL 0x11
|
||||||
#define T_PAIR 0x12
|
#define T_PAIR 0x12
|
||||||
|
|
||||||
/* Put enumerational types in 0x30..0x7f range */
|
/* Put enumerational types in 0x30..0x3f range */
|
||||||
#define T_ENUM_LO 0x30
|
#define T_ENUM_LO 0x30
|
||||||
#define T_ENUM_HI 0x7f
|
#define T_ENUM_HI 0x3f
|
||||||
|
|
||||||
#define T_ENUM_RTS 0x30
|
#define T_ENUM_RTS 0x30
|
||||||
|
|
||||||
|
@ -111,6 +110,7 @@ void val_print(struct f_val v);
|
||||||
#define T_PREFIX 0x21
|
#define T_PREFIX 0x21
|
||||||
#define T_STRING 0x22
|
#define T_STRING 0x22
|
||||||
|
|
||||||
|
#define T_RETURN 0x40
|
||||||
#define T_SET 0x80
|
#define T_SET 0x80
|
||||||
|
|
||||||
struct f_tree {
|
struct f_tree {
|
||||||
|
@ -121,4 +121,6 @@ struct f_tree {
|
||||||
|
|
||||||
#define NEW_F_VAL struct f_val * val; val = cfg_alloc(sizeof(struct f_val));
|
#define NEW_F_VAL struct f_val * val; val = cfg_alloc(sizeof(struct f_val));
|
||||||
|
|
||||||
|
/* Create pair from two letters */
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -23,6 +23,12 @@ int i;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function fifteen()
|
||||||
|
{
|
||||||
|
print "fifteen called";
|
||||||
|
return 15;
|
||||||
|
}
|
||||||
|
|
||||||
function startup()
|
function startup()
|
||||||
int i;
|
int i;
|
||||||
prefix px;
|
prefix px;
|
||||||
|
@ -58,6 +64,9 @@ ip p;
|
||||||
callme ( 4, 2 );
|
callme ( 4, 2 );
|
||||||
callme ( 7, 2 );
|
callme ( 7, 2 );
|
||||||
|
|
||||||
|
i = fifteen();
|
||||||
|
print "Testing function calls: 15 = " i;
|
||||||
|
|
||||||
print "done";
|
print "done";
|
||||||
quitbird;
|
quitbird;
|
||||||
# print "*** FAIL: this is unreachable";
|
# print "*** FAIL: this is unreachable";
|
||||||
|
|
Loading…
Reference in a new issue