Skip to content
GitLab
Projects
Groups
Snippets
Help
Loading...
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
B
BIRD Internet Routing Daemon
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Labels
Merge Requests
3
Merge Requests
3
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Operations
Operations
Environments
Packages & Registries
Packages & Registries
Container Registry
Analytics
Analytics
CI / CD
Repository
Value Stream
Wiki
Wiki
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Jobs
Commits
Open sidebar
labs
BIRD Internet Routing Daemon
Commits
d1ba927b
Commit
d1ba927b
authored
Mar 13, 2018
by
Jan Maria Matejka
Browse files
Options
Browse Files
Download
Plain Diff
Merge branch 'master' into int-new
parents
f2f5a7d9
7c601e6b
Pipeline
#34324
passed with stages
in 6 minutes and 20 seconds
Changes
5
Pipelines
1
Expand all
Hide whitespace changes
Inline
Side-by-side
Showing
5 changed files
with
333 additions
and
279 deletions
+333
-279
conf/confbase.Y
conf/confbase.Y
+2
-0
filter/config.Y
filter/config.Y
+109
-136
filter/f-util.c
filter/f-util.c
+25
-19
filter/filter.c
filter/filter.c
+111
-120
filter/filter.h
filter/filter.h
+86
-4
No files found.
conf/confbase.Y
View file @
d1ba927b
...
...
@@ -49,6 +49,8 @@ CF_DECLS
struct rtable_config *r;
struct channel_config *cc;
struct f_inst *x;
struct f_dynamic_attr fda;
struct f_static_attr fsa;
struct filter *f;
struct f_tree *e;
struct f_trie *trie;
...
...
filter/config.Y
View file @
d1ba927b
This diff is collapsed.
Click to expand it.
filter/f-util.c
View file @
d1ba927b
...
...
@@ -2,6 +2,7 @@
* Filters: utility functions
*
* Copyright 1998 Pavel Machek <pavel@ucw.cz>
* 2017 Jan Maria Matejka <mq@ucw.cz>
*
* Can be freely distributed and used under the terms of the GNU GPL.
*/
...
...
@@ -13,43 +14,48 @@
#define P(a,b) ((a<<8) | b)
struct
f_inst
*
f_new_inst
(
void
)
f_new_inst
(
enum
f_instruction_code
fi_code
)
{
struct
f_inst
*
ret
;
ret
=
cfg_alloc
(
sizeof
(
struct
f_inst
));
ret
->
code
=
ret
->
aux
=
0
;
ret
->
arg1
=
ret
->
arg2
=
ret
->
next
=
NULL
;
ret
=
cfg_allocz
(
sizeof
(
struct
f_inst
));
ret
->
fi_code
=
fi_code
;
ret
->
lineno
=
ifs
->
lino
;
return
ret
;
}
struct
f_inst
*
f_new_
dynamic_attr
(
int
type
,
int
f_type
,
int
code
)
f_new_
inst_da
(
enum
f_instruction_code
fi_code
,
struct
f_dynamic_attr
da
)
{
/* FIXME: Remove the f_type parameter? */
struct
f_inst
*
f
=
f_new_inst
();
f
->
aux
=
(
f_type
<<
8
)
|
type
;
f
->
a2
.
i
=
code
;
return
f
;
struct
f_inst
*
ret
=
f_new_inst
(
fi_code
);
ret
->
aux
=
(
da
.
f_type
<<
8
)
|
da
.
type
;
ret
->
a2
.
i
=
da
.
ea_code
;
return
ret
;
}
struct
f_inst
*
f_new_inst_sa
(
enum
f_instruction_code
fi_code
,
struct
f_static_attr
sa
)
{
struct
f_inst
*
ret
=
f_new_inst
(
fi_code
);
ret
->
aux
=
sa
.
f_type
;
ret
->
a2
.
i
=
sa
.
sa_code
;
ret
->
a1
.
i
=
sa
.
readonly
;
return
ret
;
}
/*
* Generate set_dynamic( operation( get_dynamic(), argument ) )
*/
struct
f_inst
*
f_generate_complex
(
int
operation
,
int
operation_aux
,
struct
f_
inst
*
dyn
,
struct
f_inst
*
argument
)
f_generate_complex
(
int
operation
,
int
operation_aux
,
struct
f_
dynamic_attr
da
,
struct
f_inst
*
argument
)
{
struct
f_inst
*
set_dyn
=
f_new_inst
(
),
*
oper
=
f_new_inst
(),
*
get_dyn
=
dyn
;
struct
f_inst
*
set_dyn
=
f_new_inst
_da
(
FI_EA_SET
,
da
),
*
oper
=
f_new_inst
(
operation
),
*
get_dyn
=
f_new_inst_da
(
FI_EA_GET
,
da
)
;
*
set_dyn
=
*
get_dyn
;
get_dyn
->
code
=
P
(
'e'
,
'a'
);
oper
->
code
=
operation
;
oper
->
aux
=
operation_aux
;
oper
->
a1
.
p
=
get_dyn
;
oper
->
a2
.
p
=
argument
;
set_dyn
->
code
=
P
(
'e'
,
'S'
);
set_dyn
->
a1
.
p
=
oper
;
return
set_dyn
;
}
...
...
@@ -58,7 +64,7 @@ struct f_inst *
f_generate_roa_check
(
struct
rtable_config
*
table
,
struct
f_inst
*
prefix
,
struct
f_inst
*
asn
)
{
struct
f_inst_roa_check
*
ret
=
cfg_allocz
(
sizeof
(
struct
f_inst_roa_check
));
ret
->
i
.
code
=
P
(
'R'
,
'C'
)
;
ret
->
i
.
fi_code
=
FI_ROA_CHECK
;
ret
->
i
.
lineno
=
ifs
->
lino
;
ret
->
i
.
arg1
=
prefix
;
ret
->
i
.
arg2
=
asn
;
...
...
filter/filter.c
View file @
d1ba927b
...
...
@@ -48,8 +48,6 @@
#include "conf/conf.h"
#include "filter/filter.h"
#define P(a,b) ((a<<8) | b)
#define CMP_ERROR 999
void
(
*
bt_assert_hook
)(
int
result
,
struct
f_inst
*
assert
);
...
...
@@ -462,7 +460,6 @@ val_in_range(struct f_val v1, struct f_val v2)
if
(((
v1
.
type
==
T_PAIR
)
||
(
v1
.
type
==
T_QUAD
))
&&
(
v2
.
type
==
T_CLIST
))
return
int_set_contains
(
v2
.
val
.
ad
,
v1
.
val
.
i
);
/* IP->Quad implicit conversion */
if
(
val_is_ip4
(
v1
)
&&
(
v2
.
type
==
T_CLIST
))
return
int_set_contains
(
v2
.
val
.
ad
,
ipa_to_u32
(
v1
.
val
.
ip
));
...
...
@@ -632,22 +629,20 @@ static struct f_val
interpret
(
struct
f_inst
*
what
)
{
struct
symbol
*
sym
;
struct
f_val
v1
,
v2
,
res
,
*
vp
;
struct
f_val
v1
,
v2
,
res
=
{
.
type
=
T_VOID
}
,
*
vp
;
unsigned
u1
,
u2
;
int
i
;
u32
as
;
for
(
;
what
;
what
=
what
->
next
)
{
res
.
type
=
T_VOID
;
if
(
!
what
)
return
res
;
switch
(
what
->
code
)
{
case
','
:
switch
(
what
->
fi_code
)
{
case
FI_COMMA
:
TWOARGS
;
break
;
/* Binary operators */
case
'+'
:
case
FI_ADD
:
TWOARGS_C
;
switch
(
res
.
type
=
v1
.
type
)
{
case
T_VOID
:
runtime
(
"Can't operate with values of type void"
);
...
...
@@ -655,7 +650,7 @@ interpret(struct f_inst *what)
default:
runtime
(
"Usage of unknown type"
);
}
break
;
case
'-'
:
case
FI_SUBTRACT
:
TWOARGS_C
;
switch
(
res
.
type
=
v1
.
type
)
{
case
T_VOID
:
runtime
(
"Can't operate with values of type void"
);
...
...
@@ -663,7 +658,7 @@ interpret(struct f_inst *what)
default:
runtime
(
"Usage of unknown type"
);
}
break
;
case
'*'
:
case
FI_MULTIPLY
:
TWOARGS_C
;
switch
(
res
.
type
=
v1
.
type
)
{
case
T_VOID
:
runtime
(
"Can't operate with values of type void"
);
...
...
@@ -671,7 +666,7 @@ interpret(struct f_inst *what)
default:
runtime
(
"Usage of unknown type"
);
}
break
;
case
'/'
:
case
FI_DIVIDE
:
TWOARGS_C
;
switch
(
res
.
type
=
v1
.
type
)
{
case
T_VOID
:
runtime
(
"Can't operate with values of type void"
);
...
...
@@ -681,12 +676,12 @@ interpret(struct f_inst *what)
}
break
;
case
'&'
:
case
'|'
:
case
FI_AND
:
case
FI_OR
:
ARG
(
v1
,
a1
.
p
);
if
(
v1
.
type
!=
T_BOOL
)
runtime
(
"Can't do boolean operation on non-booleans"
);
if
(
v1
.
val
.
i
==
(
what
->
code
==
'|'
))
{
if
(
v1
.
val
.
i
==
(
what
->
fi_code
==
FI_OR
))
{
res
.
type
=
T_BOOL
;
res
.
val
.
i
=
v1
.
val
.
i
;
break
;
...
...
@@ -699,7 +694,7 @@ interpret(struct f_inst *what)
res
.
val
.
i
=
v2
.
val
.
i
;
break
;
case
P
(
'm'
,
'p'
)
:
case
FI_PAIR_CONSTRUCT
:
TWOARGS
;
if
((
v1
.
type
!=
T_INT
)
||
(
v2
.
type
!=
T_INT
))
runtime
(
"Can't operate with value of non-integer type in pair constructor"
);
...
...
@@ -711,7 +706,7 @@ interpret(struct f_inst *what)
res
.
type
=
T_PAIR
;
break
;
case
P
(
'm'
,
'c'
)
:
case
FI_EC_CONSTRUCT
:
{
TWOARGS
;
...
...
@@ -757,7 +752,7 @@ interpret(struct f_inst *what)
break
;
}
case
P
(
'm'
,
'l'
)
:
case
FI_LC_CONSTRUCT
:
{
TWOARGS
;
...
...
@@ -793,12 +788,12 @@ interpret(struct f_inst *what)
res.val.i = (x); \
break;
case
P
(
'!'
,
'='
)
:
SAME
(
!
i
);
case
P
(
'='
,
'='
)
:
SAME
(
i
);
case
'<'
:
COMPARE
(
i
==-
1
);
case
P
(
'<'
,
'='
)
:
COMPARE
(
i
!=
1
);
case
FI_NEQ
:
SAME
(
!
i
);
case
FI_EQ
:
SAME
(
i
);
case
FI_LT
:
COMPARE
(
i
==-
1
);
case
FI_LTE
:
COMPARE
(
i
!=
1
);
case
'!'
:
case
FI_NOT
:
ONEARG
;
if
(
v1
.
type
!=
T_BOOL
)
runtime
(
"Not applied to non-boolean"
);
...
...
@@ -806,7 +801,7 @@ interpret(struct f_inst *what)
res
.
val
.
i
=
!
res
.
val
.
i
;
break
;
case
'~'
:
case
FI_MATCH
:
TWOARGS
;
res
.
type
=
T_BOOL
;
res
.
val
.
i
=
val_in_range
(
v1
,
v2
);
...
...
@@ -815,7 +810,7 @@ interpret(struct f_inst *what)
res
.
val
.
i
=
!!
res
.
val
.
i
;
break
;
case
P
(
'!'
,
'~'
)
:
case
FI_NOT_MATCH
:
TWOARGS
;
res
.
type
=
T_BOOL
;
res
.
val
.
i
=
val_in_range
(
v1
,
v2
);
...
...
@@ -824,12 +819,12 @@ interpret(struct f_inst *what)
res
.
val
.
i
=
!
res
.
val
.
i
;
break
;
case
P
(
'd'
,
'e'
)
:
case
FI_DEFINED
:
ONEARG
;
res
.
type
=
T_BOOL
;
res
.
val
.
i
=
(
v1
.
type
!=
T_VOID
)
&&
!
undef_value
(
v1
);
break
;
case
'T'
:
case
FI_TYPE
:
ONEARG
;
switch
(
v1
.
type
)
{
...
...
@@ -841,7 +836,7 @@ interpret(struct f_inst *what)
runtime
(
"Can't determine type of this item"
);
}
break
;
case
P
(
'I'
,
'i'
)
:
case
FI_IS_V4
:
ONEARG
;
if
(
v1
.
type
!=
T_IP
)
runtime
(
"IP version check needs an IP address"
);
...
...
@@ -850,7 +845,7 @@ interpret(struct f_inst *what)
break
;
/* Set to indirect value, a1 = variable, a2 = value */
case
's'
:
case
FI_SET
:
ARG
(
v2
,
a2
.
p
);
sym
=
what
->
a1
.
p
;
vp
=
sym
->
def
;
...
...
@@ -869,7 +864,7 @@ interpret(struct f_inst *what)
break
;
/* some constants have value in a2, some in *a1.p, strange. */
case
'c'
:
/* integer (or simple type) constant, string, set, or prefix_set */
case
FI_CONSTANT
:
/* integer (or simple type) constant, string, set, or prefix_set */
res
.
type
=
what
->
aux
;
if
(
res
.
type
==
T_PREFIX_SET
)
...
...
@@ -881,15 +876,15 @@ interpret(struct f_inst *what)
else
res
.
val
.
i
=
what
->
a2
.
i
;
break
;
case
'V'
:
case
'C'
:
case
FI_VARIABLE
:
case
FI_CONSTANT_INDIRECT
:
res
=
*
((
struct
f_val
*
)
what
->
a1
.
p
);
break
;
case
'p'
:
case
FI_PRINT
:
ONEARG
;
val_format
(
v1
,
&
f_buf
);
break
;
case
'?'
:
/* ? has really strange error value, so we can implement if ... else nicely :-) */
case
FI_CONDITION
:
/* ? has really strange error value, so we can implement if ... else nicely :-) */
ONEARG
;
if
(
v1
.
type
!=
T_BOOL
)
runtime
(
"If requires boolean expression"
);
...
...
@@ -899,10 +894,10 @@ interpret(struct f_inst *what)
}
else
res
.
val
.
i
=
1
;
res
.
type
=
T_BOOL
;
break
;
case
'0'
:
case
FI_NOP
:
debug
(
"No operation
\n
"
);
break
;
case
P
(
'p'
,
','
)
:
case
FI_PRINT_AND_DIE
:
ONEARG
;
if
((
what
->
a2
.
i
==
F_NOP
||
(
what
->
a2
.
i
!=
F_NONL
&&
what
->
a1
.
p
))
&&
!
(
f_flags
&
FF_SILENT
))
...
...
@@ -925,7 +920,7 @@ interpret(struct f_inst *what)
bug
(
"unknown return type: Can't happen"
);
}
break
;
case
'a'
:
/* rta access */
case
FI_RTA_GET
:
/* rta access */
{
ACCESS_RTE
;
struct
rta
*
rta
=
(
*
f_rte
)
->
attrs
;
...
...
@@ -948,7 +943,7 @@ interpret(struct f_inst *what)
}
}
break
;
case
P
(
'a'
,
'S'
)
:
case
FI_RTA_SET
:
ACCESS_RTE
;
ONEARG
;
if
(
what
->
aux
!=
v1
.
type
)
...
...
@@ -1000,7 +995,7 @@ interpret(struct f_inst *what)
}
}
break
;
case
P
(
'e'
,
'a'
)
:
/* Access to extended attributes */
case
FI_EA_GET
:
/* Access to extended attributes */
ACCESS_RTE
;
{
eattr
*
e
=
NULL
;
...
...
@@ -1094,7 +1089,7 @@ interpret(struct f_inst *what)
}
}
break
;
case
P
(
'e'
,
'S'
)
:
case
FI_EA_SET
:
ACCESS_RTE
;
ONEARG
;
{
...
...
@@ -1198,12 +1193,12 @@ interpret(struct f_inst *what)
}
}
break
;
case
'P'
:
case
FI_PREF_GET
:
ACCESS_RTE
;
res
.
type
=
T_INT
;
res
.
val
.
i
=
(
*
f_rte
)
->
pref
;
break
;
case
P
(
'P'
,
'S'
)
:
case
FI_PREF_SET
:
ACCESS_RTE
;
ONEARG
;
if
(
v1
.
type
!=
T_INT
)
...
...
@@ -1213,7 +1208,7 @@ interpret(struct f_inst *what)
f_rte_cow
();
(
*
f_rte
)
->
pref
=
v1
.
val
.
i
;
break
;
case
'L'
:
/* Get length of */
case
FI_LENGTH
:
/* Get length of */
ONEARG
;
res
.
type
=
T_INT
;
switch
(
v1
.
type
)
{
...
...
@@ -1225,7 +1220,7 @@ interpret(struct f_inst *what)
default:
runtime
(
"Prefix, path, clist or eclist expected"
);
}
break
;
case
P
(
'R'
,
'm'
)
:
/* Get ROA max prefix length */
case
FI_ROA_MAXLEN
:
/* Get ROA max prefix length */
ONEARG
;
if
(
v1
.
type
!=
T_NET
||
!
net_is_roa
(
v1
.
val
.
net
))
runtime
(
"ROA expected"
);
...
...
@@ -1235,7 +1230,7 @@ interpret(struct f_inst *what)
((
net_addr_roa4
*
)
v1
.
val
.
net
)
->
max_pxlen
:
((
net_addr_roa6
*
)
v1
.
val
.
net
)
->
max_pxlen
;
break
;
case
P
(
'R'
,
'a'
)
:
/* Get ROA ASN */
case
FI_ROA_ASN
:
/* Get ROA ASN */
ONEARG
;
if
(
v1
.
type
!=
T_NET
||
!
net_is_roa
(
v1
.
val
.
net
))
runtime
(
"ROA expected"
);
...
...
@@ -1245,14 +1240,14 @@ interpret(struct f_inst *what)
((
net_addr_roa4
*
)
v1
.
val
.
net
)
->
asn
:
((
net_addr_roa6
*
)
v1
.
val
.
net
)
->
asn
;
break
;
case
P
(
'c'
,
'p'
)
:
/* Convert prefix to ... */
case
FI_IP
:
/* Convert prefix to ... */
ONEARG
;
if
(
v1
.
type
!=
T_NET
)
runtime
(
"Prefix expected"
);
res
.
type
=
T_IP
;
res
.
val
.
ip
=
net_prefix
(
v1
.
val
.
net
);
break
;
case
P
(
'R'
,
'D'
)
:
case
FI_ROUTE_DISTINGUISHER
:
ONEARG
;
if
(
v1
.
type
!=
T_NET
)
runtime
(
"Prefix expected"
);
...
...
@@ -1261,7 +1256,7 @@ interpret(struct f_inst *what)
res
.
type
=
T_RD
;
res
.
val
.
ec
=
net_rd
(
v1
.
val
.
net
);
break
;
case
P
(
'a'
,
'f'
)
:
/* Get first ASN from AS PATH */
case
FI_AS_PATH_FIRST
:
/* Get first ASN from AS PATH */
ONEARG
;
if
(
v1
.
type
!=
T_PATH
)
runtime
(
"AS path expected"
);
...
...
@@ -1271,7 +1266,7 @@ interpret(struct f_inst *what)
res
.
type
=
T_INT
;
res
.
val
.
i
=
as
;
break
;
case
P
(
'a'
,
'l'
)
:
/* Get last ASN from AS PATH */
case
FI_AS_PATH_LAST
:
/* Get last ASN from AS PATH */
ONEARG
;
if
(
v1
.
type
!=
T_PATH
)
runtime
(
"AS path expected"
);
...
...
@@ -1281,7 +1276,7 @@ interpret(struct f_inst *what)
res
.
type
=
T_INT
;
res
.
val
.
i
=
as
;
break
;
case
P
(
'a'
,
'L'
)
:
/* Get last ASN from non-aggregated part of AS PATH */
case
FI_AS_PATH_LAST_NAG
:
/* Get last ASN from non-aggregated part of AS PATH */
ONEARG
;
if
(
v1
.
type
!=
T_PATH
)
runtime
(
"AS path expected"
);
...
...
@@ -1289,23 +1284,23 @@ interpret(struct f_inst *what)
res
.
type
=
T_INT
;
res
.
val
.
i
=
as_path_get_last_nonaggregated
(
v1
.
val
.
ad
);
break
;
case
'r'
:
case
FI_RETURN
:
ONEARG
;
res
=
v1
;
res
.
type
|=
T_RETURN
;
return
res
;
case
P
(
'c'
,
'a'
)
:
/* CALL: this is special: if T_RETURN and returning some value, mask it out */
case
FI_CALL
:
/* CALL: this is special: if T_RETURN and returning some value, mask it out */
ONEARG
;
res
=
interpret
(
what
->
a2
.
p
);
if
(
res
.
type
==
T_RETURN
)
return
res
;
res
.
type
&=
~
T_RETURN
;
break
;
case
P
(
'c'
,
'v'
)
:
/* Clear local variables */
case
FI_CLEAR_LOCAL_VARS
:
/* Clear local variables */
for
(
sym
=
what
->
a1
.
p
;
sym
!=
NULL
;
sym
=
sym
->
aux2
)
((
struct
f_val
*
)
sym
->
def
)
->
type
=
T_VOID
;
break
;
case
P
(
'S'
,
'W'
)
:
case
FI_SWITCH
:
ONEARG
;
{
struct
f_tree
*
t
=
find_tree
(
what
->
a2
.
p
,
v1
);
...
...
@@ -1324,7 +1319,7 @@ interpret(struct f_inst *what)
return
res
;
}
break
;
case
P
(
'i'
,
'M'
)
:
/* IP.MASK(val) */
case
FI_IP_MASK
:
/* IP.MASK(val) */
TWOARGS
;
if
(
v2
.
type
!=
T_INT
)
runtime
(
"Integer expected"
);
...
...
@@ -1337,11 +1332,11 @@ interpret(struct f_inst *what)
ipa_from_ip6
(
ip6_and
(
ipa_to_ip6
(
v1
.
val
.
ip
),
ip6_mkmask
(
v2
.
val
.
i
)));
break
;
case
'E'
:
/* Create empty attribute */
case
FI_EMPTY
:
/* Create empty attribute */
res
.
type
=
what
->
aux
;
res
.
val
.
ad
=
adata_empty
(
f_pool
,
0
);
break
;
case
P
(
'A'
,
'p'
)
:
/* Path prepend */
case
FI_PATH_PREPEND
:
/* Path prepend */
TWOARGS
;
if
(
v1
.
type
!=
T_PATH
)
runtime
(
"Can't prepend to non-path"
);
...
...
@@ -1352,7 +1347,7 @@ interpret(struct f_inst *what)
res
.
val
.
ad
=
as_path_prepend
(
f_pool
,
v1
.
val
.
ad
,
v2
.
val
.
i
);
break
;
case
P
(
'C'
,
'a'
)
:
/* (Extended) Community list add or delete */
case
FI_CLIST_ADD_DEL
:
/* (Extended) Community list add or delete */
TWOARGS
;
if
(
v1
.
type
==
T_PATH
)
{
...
...
@@ -1518,8 +1513,7 @@ interpret(struct f_inst *what)
break
;
case
P
(
'R'
,
'C'
):
/* ROA Check */
case
FI_ROA_CHECK
:
/* ROA Check */
if
(
what
->
arg1
)
{
TWOARGS
;
...
...
@@ -1559,14 +1553,14 @@ interpret(struct f_inst *what)
break
;
case
P
(
'f'
,
'm'
)
:
/* Format */
case
FI_FORMAT
:
/* Format */
ONEARG
;
res
.
type
=
T_STRING
;
res
.
val
.
s
=
val_format_str
(
v1
);
break
;
case
P
(
'a'
,
's'
)
:
/* Birdtest Assert */
case
FI_ASSERT
:
/* Birdtest Assert */
ONEARG
;
if
(
v1
.
type
!=
T_BOOL
)
...
...
@@ -1579,10 +1573,8 @@ interpret(struct f_inst *what)
break
;
default:
bug
(
"Unknown instruction %d (%c)"
,
what
->
code
,
what
->
code
&
0xff
);
}
if
(
what
->
next
)
return
interpret
(
what
->
next
);
bug
(
"Unknown instruction %d (%c)"
,
what
->
fi_code
,
what
->
fi_code
&
0xff
);
}}
return
res
;
}
...
...
@@ -1609,40 +1601,39 @@ i_same(struct f_inst *f1, struct f_inst *f2)
return
1
;
if
(
f1
->
aux
!=
f2
->
aux
)
return
0
;
if
(
f1
->
code
!=
f2
->
code
)
if
(
f1
->
fi_code
!=
f2
->
fi_
code
)
return
0
;
if
(
f1
==
f2
)
/* It looks strange, but it is possible with call rewriting trickery */
return
1
;
switch
(
f1
->
code
)
{
case
','
:
/* fall through */
case
'+'
:
case
'-'
:
case
'*'
:
case
'/'
:
case
'|'
:
case
'&'
:
case
P
(
'm'
,
'p'
):
case
P
(
'm'
,
'c'
):
case
P
(
'!'
,
'='
):
case
P
(
'='
,
'='
):
case
'<'
:
case
P
(
'<'
,
'='
):
TWOARGS
;
break
;
case
'!'
:
ONEARG
;
break
;
case
P
(
'!'
,
'~'
):
case
'~'
:
TWOARGS
;
break
;
case
P
(
'd'
,
'e'
):
ONEARG
;
break
;
case
'T'
:
ONEARG
;
break
;
case
P
(
'n'
,
'T'
):
break
;
case
P
(
'm'
,
'l'
):
switch
(
f1
->
fi_code
)
{
case
FI_COMMA
:
/* fall through */
case
FI_ADD
:
case
FI_SUBTRACT
:
case
FI_MULTIPLY
:
case
FI_DIVIDE
:
case
FI_OR
:
case
FI_AND
:
case
FI_PAIR_CONSTRUCT
:
case
FI_EC_CONSTRUCT
:
case
FI_NEQ
:
case
FI_EQ
:
case
FI_LT
:
case
FI_LTE
:
TWOARGS
;
break
;
case
FI_NOT
:
ONEARG
;
break
;
case
FI_NOT_MATCH
:
case
FI_MATCH
:
TWOARGS
;
break
;
case
FI_DEFINED
:
ONEARG
;
break
;
case
FI_TYPE
:
ONEARG
;
break
;
case
FI_LC_CONSTRUCT
:
TWOARGS
;
if
(
!
i_same
(
INST3
(
f1
).
p
,
INST3
(
f2
).
p
))
return
0
;
break
;
case
's'
:
case
FI_SET
:
ARG
(
v2
,
a2
.
p
);
{
struct
symbol
*
s1
,
*
s2
;
...
...
@@ -1655,7 +1646,7 @@ i_same(struct f_inst *f1, struct f_inst *f2)
}
break
;
case
'c'
:
case
FI_CONSTANT
:
switch
(
f1
->
aux
)
{
case
T_PREFIX_SET
:
...
...
@@ -1678,44 +1669,44 @@ i_same(struct f_inst *f1, struct f_inst *f2)
}
break
;
case
'C'
:
case
FI_CONSTANT_INDIRECT
:
if
(
!
val_same
(
*
(
struct
f_val
*
)
f1
->
a1
.
p
,
*
(
struct
f_val
*
)
f2
->
a1
.
p
))
return
0
;
break
;
case
'V'
:
case
FI_VARIABLE
:
if
(
strcmp
((
char
*
)
f1
->
a2
.
p
,
(
char
*
)
f2
->
a2
.
p
))
return
0
;
break
;
case
'p'
:
case
'L'
:
ONEARG
;
break
;
case
'?'
:
TWOARGS
;
break
;
case
'0'
:
case
'E'
:
break
;
case
P
(
'p'
,
','
)
:
ONEARG
;
A2_SAME
;
break
;
case
'P'
:
case
'a'
:
A2_SAME
;
break
;
case
P
(
'e'
,
'a'
)
:
A2_SAME
;
break
;
case
P
(
'P'
,
'S'
)
:
case
P
(
'a'
,
'S'
)
:
case
P
(
'e'
,
'S'
)
:
ONEARG
;
A2_SAME
;
break
;
case
'r'
:
ONEARG
;
break
;
case
P
(
'c'
,
'p'
)
:
ONEARG
;
break
;
case
P
(
'R'
,
'D'
)
:
ONEARG
;
break
;
case
P
(
'c'
,
'a'
)
:
/* Call rewriting trickery to avoid exponential behaviour */
case
FI_PRINT
:
case
FI_LENGTH
:
ONEARG
;
break
;
case
FI_CONDITION
:
TWOARGS
;
break
;
case
FI_NOP
:
case
FI_EMPTY
:
break
;
case
FI_PRINT_AND_DIE
:
ONEARG
;
A2_SAME
;
break
;
case
FI_PREF_GET
:
case
FI_RTA_GET
:
A2_SAME
;
break
;
case
FI_EA_GET
:
A2_SAME
;
break
;
case
FI_PREF_SET
:
case
FI_RTA_SET
:
case
FI_EA_SET
:
ONEARG
;
A2_SAME
;
break
;
case
FI_RETURN
:
ONEARG
;
break
;
case
FI_IP
:
ONEARG
;
break
;
case
FI_ROUTE_DISTINGUISHER
:
ONEARG
;
break
;
case
FI_CALL
:
/* Call rewriting trickery to avoid exponential behaviour */
ONEARG
;
if
(
!
i_same
(
f1
->
a2
.
p
,
f2
->
a2
.
p
))
return
0
;
f2
->
a2
.
p
=
f1
->
a2
.
p
;
break
;
case
P
(
'c'
,
'v'
)
:
break
;
/* internal instruction */
case
P
(
'S'
,
'W'
)
:
ONEARG
;
if
(
!
same_tree
(
f1
->
a2
.
p
,
f2
->
a2
.
p
))
return
0
;
break
;
case
P
(
'i'
,
'M'
)
:
TWOARGS
;
break
;