forked from osmocom/wireshark
dfilter: Add location tracking to scanner and use it to report errors
Add location tracking as a column offset and length from offset to the scanner. Our input is a single line only so we don't need to track line offset. Record that information in the syntax tree. Return the error location in dfilter_compile(). Use it in dftest to mark the location of the error in the filter string. Later it would be nice to use the location in the GUI as well. $ dftest "ip.proto == aaaaaa and tcp.port == 123" Filter: ip.proto == aaaaaa and tcp.port == 123 dftest: "aaaaaa" cannot be found among the possible values for ip.proto. ip.proto == aaaaaa and tcp.port == 123 ^~~~~~
This commit is contained in:
parent
da19379eb5
commit
4d9470e7dd
50
dftest.c
50
dftest.c
|
@ -40,6 +40,23 @@
|
|||
static void dftest_cmdarg_err(const char *fmt, va_list ap);
|
||||
static void dftest_cmdarg_err_cont(const char *fmt, va_list ap);
|
||||
|
||||
static void
|
||||
putloc(FILE *fp, int start, size_t len)
|
||||
{
|
||||
if (start < 0)
|
||||
return;
|
||||
|
||||
for (int i = 0; i < start; i++) {
|
||||
fputc(' ', fp);
|
||||
}
|
||||
fputc('^', fp);
|
||||
|
||||
for (size_t l = len; l > 1; l--) {
|
||||
fputc('~', fp);
|
||||
}
|
||||
fputc('\n', fp);
|
||||
}
|
||||
|
||||
int
|
||||
main(int argc, char **argv)
|
||||
{
|
||||
|
@ -57,8 +74,10 @@ main(int argc, char **argv)
|
|||
cfile_close_failure_message
|
||||
};
|
||||
char *text;
|
||||
char *expanded_text;
|
||||
dfilter_t *df;
|
||||
gchar *err_msg;
|
||||
dfilter_loc_t err_loc;
|
||||
|
||||
cmdarg_err_init(dftest_cmdarg_err, dftest_cmdarg_err_cont);
|
||||
|
||||
|
@ -130,27 +149,44 @@ main(int argc, char **argv)
|
|||
/* Get filter text */
|
||||
text = get_args_as_string(argc, argv, 1);
|
||||
|
||||
/* Compile it */
|
||||
if (!dfilter_compile2(text, &df, &err_msg, TRUE)) {
|
||||
/* Expand macros. */
|
||||
expanded_text = dfilter_expand(text, &err_msg);
|
||||
if (expanded_text == NULL) {
|
||||
fprintf(stderr, "dftest: %s\n", err_msg);
|
||||
g_free(err_msg);
|
||||
epan_cleanup();
|
||||
g_free(text);
|
||||
epan_cleanup();
|
||||
exit(2);
|
||||
}
|
||||
g_free(text);
|
||||
text = NULL;
|
||||
|
||||
printf("Filter: %s\n", expanded_text);
|
||||
|
||||
/* Compile it */
|
||||
if (!dfilter_compile_real(expanded_text, &df, &err_msg, &err_loc,
|
||||
"dftest", TRUE, FALSE)) {
|
||||
fprintf(stderr, "dftest: %s\n", err_msg);
|
||||
fprintf(stderr, "\t%s\n", expanded_text);
|
||||
fputc('\t', stderr);
|
||||
putloc(stderr, err_loc.col_start, err_loc.col_len);
|
||||
g_free(err_msg);
|
||||
g_free(expanded_text);
|
||||
epan_cleanup();
|
||||
exit(2);
|
||||
}
|
||||
|
||||
if (df == NULL) {
|
||||
printf("Filter is empty\n");
|
||||
printf("Filter is empty.\n");
|
||||
}
|
||||
else {
|
||||
printf("Filter text:\n%s\n\n", dfilter_text(df));
|
||||
printf("Syntax tree:\n%s\n\n", dfilter_syntax_tree(df));
|
||||
printf("\nSyntax tree:\n%s\n\n", dfilter_syntax_tree(df));
|
||||
dfilter_dump(df);
|
||||
}
|
||||
|
||||
dfilter_free(df);
|
||||
epan_cleanup();
|
||||
g_free(text);
|
||||
g_free(expanded_text);
|
||||
exit(0);
|
||||
}
|
||||
|
||||
|
|
|
@ -44,6 +44,8 @@ typedef struct {
|
|||
GPtrArray *deprecated;
|
||||
GHashTable *references; /* hfinfo -> pointer to GSList of fvalues */
|
||||
GHashTable *loaded_references;
|
||||
char *expanded_text;
|
||||
stloc_t err_loc;
|
||||
} dfwork_t;
|
||||
|
||||
/*
|
||||
|
@ -53,6 +55,8 @@ typedef struct {
|
|||
dfwork_t *dfw;
|
||||
GString* quoted_string;
|
||||
gboolean raw_string;
|
||||
stloc_t string_loc;
|
||||
stloc_t location;
|
||||
} df_scanner_state_t;
|
||||
|
||||
/* Constructor/Destructor prototypes for Lemon Parser */
|
||||
|
@ -66,14 +70,20 @@ void Dfilter(void*, int, stnode_t*, dfwork_t*);
|
|||
#define SCAN_FAILED -1 /* not 0, as that means end-of-input */
|
||||
|
||||
void
|
||||
dfilter_vfail(dfwork_t *dfw, const char *format, va_list args);
|
||||
dfilter_vfail(dfwork_t *dfw, stloc_t *err_loc,
|
||||
const char *format, va_list args);
|
||||
|
||||
void
|
||||
dfilter_fail(dfwork_t *dfw, const char *format, ...) G_GNUC_PRINTF(2, 3);
|
||||
dfilter_fail(dfwork_t *dfw, stloc_t *err_loc,
|
||||
const char *format, ...) G_GNUC_PRINTF(3, 4);
|
||||
|
||||
WS_NORETURN
|
||||
void
|
||||
dfilter_fail_throw(dfwork_t *dfw, long code, const char *format, ...) G_GNUC_PRINTF(3, 4);
|
||||
dfilter_fail_throw(dfwork_t *dfw, stloc_t *err_loc,
|
||||
long code, const char *format, ...) G_GNUC_PRINTF(4, 5);
|
||||
|
||||
void
|
||||
dfw_set_error_location(dfwork_t *dfw, stloc_t *err_loc);
|
||||
|
||||
void
|
||||
add_deprecated_token(dfwork_t *dfw, const char *token);
|
||||
|
|
|
@ -42,7 +42,8 @@ static void* ParserObj = NULL;
|
|||
dfwork_t *global_dfw;
|
||||
|
||||
void
|
||||
dfilter_vfail(dfwork_t *dfw, const char *format, va_list args)
|
||||
dfilter_vfail(dfwork_t *dfw, stloc_t *loc,
|
||||
const char *format, va_list args)
|
||||
{
|
||||
/* Flag a syntax error. This is currently only used in
|
||||
* the grammar parsing stage to terminate the parsing
|
||||
|
@ -54,29 +55,42 @@ dfilter_vfail(dfwork_t *dfw, const char *format, va_list args)
|
|||
return;
|
||||
|
||||
dfw->error_message = ws_strdup_vprintf(format, args);
|
||||
if (loc) {
|
||||
dfw->err_loc = *loc;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
dfilter_fail(dfwork_t *dfw, const char *format, ...)
|
||||
dfilter_fail(dfwork_t *dfw, stloc_t *loc,
|
||||
const char *format, ...)
|
||||
{
|
||||
va_list args;
|
||||
|
||||
va_start(args, format);
|
||||
dfilter_vfail(dfw, format, args);
|
||||
dfilter_vfail(dfw, loc, format, args);
|
||||
va_end(args);
|
||||
}
|
||||
|
||||
void
|
||||
dfilter_fail_throw(dfwork_t *dfw, long code, const char *format, ...)
|
||||
dfilter_fail_throw(dfwork_t *dfw, stloc_t *loc,
|
||||
long code, const char *format, ...)
|
||||
{
|
||||
va_list args;
|
||||
|
||||
va_start(args, format);
|
||||
dfilter_vfail(dfw, format, args);
|
||||
dfilter_vfail(dfw, loc, format, args);
|
||||
va_end(args);
|
||||
THROW(code);
|
||||
}
|
||||
|
||||
void
|
||||
dfw_set_error_location(dfwork_t *dfw, stloc_t *loc)
|
||||
{
|
||||
/* Set new location. */
|
||||
ws_assert(loc);
|
||||
dfw->err_loc = *loc;
|
||||
}
|
||||
|
||||
/*
|
||||
* Tries to convert an STTYPE_UNPARSED to a STTYPE_FIELD. If it's not registered as
|
||||
* a field pass UNPARSED to the semantic check.
|
||||
|
@ -254,6 +268,8 @@ dfwork_free(dfwork_t *dfw)
|
|||
if (dfw->deprecated)
|
||||
g_ptr_array_unref(dfw->deprecated);
|
||||
|
||||
g_free(dfw->expanded_text);
|
||||
|
||||
/*
|
||||
* We don't free the error message string; our caller will return
|
||||
* it to its caller.
|
||||
|
@ -321,12 +337,18 @@ add_deprecated_token(dfwork_t *dfw, const char *token)
|
|||
g_ptr_array_add(deprecated, g_strdup(token));
|
||||
}
|
||||
|
||||
char *
|
||||
dfilter_expand(const char *expr, char **err_ret)
|
||||
{
|
||||
return dfilter_macro_apply(expr, err_ret);
|
||||
}
|
||||
|
||||
gboolean
|
||||
dfilter_compile_real(const gchar *text, dfilter_t **dfp,
|
||||
gchar **error_ret, const char *caller,
|
||||
gboolean save_tree)
|
||||
gchar **error_ret, dfilter_loc_t *loc_ptr,
|
||||
const char *caller, gboolean save_tree,
|
||||
gboolean apply_macros)
|
||||
{
|
||||
gchar *expanded_text;
|
||||
int token;
|
||||
dfilter_t *dfilter;
|
||||
dfwork_t *dfw;
|
||||
|
@ -364,28 +386,32 @@ dfilter_compile_real(const gchar *text, dfilter_t **dfp,
|
|||
|
||||
dfw = dfwork_new();
|
||||
|
||||
expanded_text = dfilter_macro_apply(text, &dfw->error_message);
|
||||
if (expanded_text == NULL) {
|
||||
goto FAILURE;
|
||||
if (apply_macros) {
|
||||
dfw->expanded_text = dfilter_macro_apply(text, &dfw->error_message);
|
||||
if (dfw->expanded_text == NULL) {
|
||||
goto FAILURE;
|
||||
}
|
||||
ws_noisy("Expanded text: %s", dfw->expanded_text);
|
||||
}
|
||||
else {
|
||||
dfw->expanded_text = g_strdup(text);
|
||||
ws_noisy("Verbatim text: %s", dfw->expanded_text);
|
||||
}
|
||||
|
||||
ws_noisy("Expanded text: %s", expanded_text);
|
||||
|
||||
if (df_lex_init(&scanner) != 0) {
|
||||
dfw->error_message = ws_strdup_printf("Can't initialize scanner: %s", g_strerror(errno));
|
||||
goto FAILURE;
|
||||
}
|
||||
|
||||
in_buffer = df__scan_string(expanded_text, scanner);
|
||||
in_buffer = df__scan_string(dfw->expanded_text, scanner);
|
||||
|
||||
memset(&state, 0, sizeof(state));
|
||||
state.dfw = dfw;
|
||||
state.quoted_string = NULL;
|
||||
state.raw_string = FALSE;
|
||||
|
||||
df_set_extra(&state, scanner);
|
||||
|
||||
while (1) {
|
||||
df_lval = stnode_new(STTYPE_UNINITIALIZED, NULL, NULL);
|
||||
df_lval = stnode_new(STTYPE_UNINITIALIZED, NULL, NULL, NULL);
|
||||
token = df_lex(scanner);
|
||||
|
||||
/* Check for scanner failure */
|
||||
|
@ -473,7 +499,8 @@ dfilter_compile_real(const gchar *text, dfilter_t **dfp,
|
|||
dfw->insns = NULL;
|
||||
dfilter->interesting_fields = dfw_interesting_fields(dfw,
|
||||
&dfilter->num_interesting_fields);
|
||||
dfilter->expanded_text = ws_strdup(expanded_text);
|
||||
dfilter->expanded_text = dfw->expanded_text;
|
||||
dfw->expanded_text = NULL;
|
||||
dfilter->references = dfw->references;
|
||||
dfw->references = NULL;
|
||||
|
||||
|
@ -504,7 +531,6 @@ dfilter_compile_real(const gchar *text, dfilter_t **dfp,
|
|||
ws_log(WS_LOG_DOMAIN, LOG_LEVEL_INFO, "Compiled display filter: %s", text);
|
||||
else
|
||||
ws_debug("Compiled empty filter (successfully).");
|
||||
wmem_free(NULL, expanded_text);
|
||||
return TRUE;
|
||||
|
||||
FAILURE:
|
||||
|
@ -521,11 +547,14 @@ FAILURE:
|
|||
else {
|
||||
g_free(dfw->error_message);
|
||||
}
|
||||
if (loc_ptr != NULL) {
|
||||
loc_ptr->col_start = dfw->err_loc.col_start;
|
||||
loc_ptr->col_len = dfw->err_loc.col_len;
|
||||
}
|
||||
}
|
||||
|
||||
global_dfw = NULL;
|
||||
dfwork_free(dfw);
|
||||
wmem_free(NULL, expanded_text);
|
||||
*dfp = NULL;
|
||||
return FALSE;
|
||||
}
|
||||
|
|
|
@ -32,6 +32,11 @@ dfilter_init(void);
|
|||
void
|
||||
dfilter_cleanup(void);
|
||||
|
||||
/* Perform macro expansion. */
|
||||
WS_DLL_PUBLIC
|
||||
char *
|
||||
dfilter_expand(const char *expr, char **err_ret);
|
||||
|
||||
/* Compiles a string to a dfilter_t.
|
||||
* On success, sets the dfilter* pointed to by dfp
|
||||
* to either a NULL pointer (if the filter is a null
|
||||
|
@ -46,17 +51,21 @@ dfilter_cleanup(void);
|
|||
*
|
||||
* Returns TRUE on success, FALSE on failure.
|
||||
*/
|
||||
|
||||
typedef struct _dfilter_loc {
|
||||
int col_start;
|
||||
size_t col_len;
|
||||
} dfilter_loc_t;
|
||||
|
||||
WS_DLL_PUBLIC
|
||||
gboolean
|
||||
dfilter_compile_real(const gchar *text, dfilter_t **dfp,
|
||||
gchar **err_msg, const char *caller,
|
||||
gboolean save_tree);
|
||||
gchar **err_msg, dfilter_loc_t *loc_ptr,
|
||||
const char *caller, gboolean save_tree,
|
||||
gboolean apply_macros);
|
||||
|
||||
#define dfilter_compile(text, dfp, err_msg) \
|
||||
dfilter_compile_real(text, dfp, err_msg, __func__, FALSE)
|
||||
|
||||
#define dfilter_compile2(text, dfp, err_msg, save_tree) \
|
||||
dfilter_compile_real(text, dfp, err_msg, __func__, save_tree)
|
||||
dfilter_compile_real(text, dfp, err_msg, NULL, __func__, FALSE, TRUE)
|
||||
|
||||
/* Frees all memory used by dfilter, and frees
|
||||
* the dfilter itself. */
|
||||
|
|
|
@ -19,8 +19,8 @@
|
|||
#include <epan/exceptions.h>
|
||||
#include <wsutil/ws_assert.h>
|
||||
|
||||
#define FAIL(dfw, ...) \
|
||||
dfilter_fail_throw(dfw, TypeError, __VA_ARGS__)
|
||||
#define FAIL(dfw, node, ...) \
|
||||
dfilter_fail_throw(dfw, stnode_location(node), TypeError, __VA_ARGS__)
|
||||
|
||||
/* Convert an FT_STRING using a callback function */
|
||||
static gboolean
|
||||
|
@ -183,7 +183,7 @@ ul_semcheck_is_field_string(dfwork_t *dfw, const char *func_name,
|
|||
return;
|
||||
}
|
||||
}
|
||||
FAIL(dfw, "Only string type fields can be used as parameter for %s()", func_name);
|
||||
FAIL(dfw, st_node, "Only string type fields can be used as parameter for %s()", func_name);
|
||||
}
|
||||
|
||||
static void
|
||||
|
@ -195,7 +195,7 @@ ul_semcheck_is_field(dfwork_t *dfw, const char *func_name,
|
|||
if (stnode_type_id(st_node) == STTYPE_FIELD)
|
||||
return;
|
||||
|
||||
FAIL(dfw, "Only fields can be used as parameter for %s()", func_name);
|
||||
FAIL(dfw, st_node, "Only fields can be used as parameter for %s()", func_name);
|
||||
}
|
||||
|
||||
static void
|
||||
|
@ -245,9 +245,9 @@ ul_semcheck_string_param(dfwork_t *dfw, const char *func_name,
|
|||
default:
|
||||
break;
|
||||
}
|
||||
FAIL(dfw, "String conversion for field \"%s\" is not supported", hfinfo->abbrev);
|
||||
FAIL(dfw, st_node, "String conversion for field \"%s\" is not supported", hfinfo->abbrev);
|
||||
}
|
||||
FAIL(dfw, "Only fields can be used as parameter for %s()", func_name);
|
||||
FAIL(dfw, st_node, "Only fields can be used as parameter for %s()", func_name);
|
||||
}
|
||||
|
||||
/* The table of all display-filter functions */
|
||||
|
|
|
@ -21,6 +21,8 @@
|
|||
static stnode_t *
|
||||
new_function(dfwork_t *dfw, stnode_t *node);
|
||||
|
||||
#define FAIL(dfw, node, ...) dfilter_fail(dfw, stnode_location(node), __VA_ARGS__)
|
||||
|
||||
/* End of C code */
|
||||
}
|
||||
|
||||
|
@ -55,10 +57,10 @@ new_function(dfwork_t *dfw, stnode_t *node);
|
|||
any "error" symbols are shifted, if possible. */
|
||||
%syntax_error {
|
||||
if (!TOKEN) {
|
||||
dfilter_fail(dfw, "Unexpected end of filter expression.");
|
||||
dfilter_fail(dfw, NULL, "Unexpected end of filter expression.");
|
||||
return;
|
||||
}
|
||||
dfilter_fail(dfw, "\"%s\" was unexpected in this context.", stnode_token(TOKEN));
|
||||
FAIL(dfw, TOKEN, "\"%s\" was unexpected in this context.", stnode_token(TOKEN));
|
||||
}
|
||||
|
||||
/* When a parse fails, mark an error. This occurs after
|
||||
|
@ -213,8 +215,8 @@ comparison_test(T) ::= arithmetic_expr(E) cmp_op(O) comparison_test(R).
|
|||
L = O;
|
||||
sttype_test_set2_args(L, E, stnode_dup(F));
|
||||
|
||||
T = stnode_new_test(TEST_OP_AND, NULL);
|
||||
sttype_test_set2_args(T, L, R);
|
||||
T = stnode_new(STTYPE_TEST, NULL, NULL, NULL);
|
||||
sttype_test_set2(T, TEST_OP_AND, L, R);
|
||||
}
|
||||
|
||||
relation_test(T) ::= comparison_test(C). { T = C; }
|
||||
|
@ -246,7 +248,7 @@ relation_test(T) ::= entity(E) TEST_NOT(P) TEST_IN(O) set(S).
|
|||
|
||||
set(S) ::= LBRACE set_list(L) RBRACE.
|
||||
{
|
||||
S = stnode_new(STTYPE_SET, L, NULL);
|
||||
S = stnode_new(STTYPE_SET, L, NULL, NULL);
|
||||
}
|
||||
|
||||
set_list(L) ::= set_element(N).
|
||||
|
@ -291,7 +293,7 @@ set_element(N) ::= set_entity(X) DOTDOT set_entity(Y).
|
|||
|
||||
range(R) ::= entity(E) LBRACKET range_node_list(L) RBRACKET.
|
||||
{
|
||||
R = stnode_new(STTYPE_RANGE, NULL, NULL);
|
||||
R = stnode_new(STTYPE_RANGE, NULL, NULL, NULL);
|
||||
sttype_range_set(R, E, L);
|
||||
|
||||
/* Delete the list, but not the drange_nodes that
|
||||
|
@ -321,7 +323,7 @@ range_node_list(L) ::= range_node_list(P) COMMA RANGE_NODE(N).
|
|||
|
||||
df_func_def_t *def = df_func_lookup(name);
|
||||
if (!def) {
|
||||
dfilter_fail(dfw, "Function '%s' does not exist", name);
|
||||
FAIL(dfw, node, "Function '%s' does not exist", name);
|
||||
}
|
||||
stnode_replace(node, STTYPE_FUNCTION, def);
|
||||
return node;
|
||||
|
|
|
@ -79,20 +79,25 @@ DIAG_OFF_FLEX
|
|||
|
||||
stnode_t *df_lval;
|
||||
|
||||
static int set_lval_simple(int token, const char *token_value, sttype_id_t type_id);
|
||||
static int set_lval_str(int token, const char *token_value);
|
||||
static int set_lval_simple(df_scanner_state_t *state, int token, const char *token_value, sttype_id_t type_id);
|
||||
static int set_lval_str(df_scanner_state_t *state, int token, const char *token_value);
|
||||
|
||||
static int set_lval_quoted_string(dfwork_t *dfw, int token, GString *quoted_string);
|
||||
static int set_lval_charconst(dfwork_t *dfw, int token, GString *quoted_string);
|
||||
static int set_lval_range_node(dfwork_t *dfw, int token, const char *token_value);
|
||||
static int set_lval_field(dfwork_t *dfw, int token, const char *token_value);
|
||||
static int set_lval_quoted_string(df_scanner_state_t *state, int token, GString *quoted_string);
|
||||
static int set_lval_charconst(df_scanner_state_t *state, int token, GString *quoted_string);
|
||||
static int set_lval_range_node(df_scanner_state_t *state, int token, const char *token_value);
|
||||
static int set_lval_field(df_scanner_state_t *state, int token, const char *token_value);
|
||||
|
||||
#define simple(token) set_lval_simple(token, yytext, STTYPE_UNINITIALIZED)
|
||||
#define test(token) set_lval_simple(token, yytext, STTYPE_TEST)
|
||||
#define math(token) set_lval_simple(token, yytext, STTYPE_ARITHMETIC)
|
||||
#define simple(token) (update_location(yyextra, yytext), set_lval_simple(yyextra, token, yytext, STTYPE_UNINITIALIZED))
|
||||
#define test(token) (update_location(yyextra, yytext), set_lval_simple(yyextra, token, yytext, STTYPE_TEST))
|
||||
#define math(token) (update_location(yyextra, yytext), set_lval_simple(yyextra, token, yytext, STTYPE_ARITHMETIC))
|
||||
|
||||
static gboolean append_escaped_char(dfwork_t *dfw, GString *str, char c);
|
||||
static gboolean parse_charconst(dfwork_t *dfw, const char *s, unsigned long *valuep);
|
||||
static gboolean append_escaped_char(df_scanner_state_t *state, GString *str, char c);
|
||||
static gboolean parse_charconst(df_scanner_state_t *state, const char *s, unsigned long *valuep);
|
||||
|
||||
static void update_location(df_scanner_state_t *state, const char *text);
|
||||
static void update_string_loc(df_scanner_state_t *state, const char *text);
|
||||
|
||||
#define FAIL(...) dfilter_fail(yyextra->dfw, &yyextra->location, __VA_ARGS__)
|
||||
|
||||
/*
|
||||
* Sleazy hack to suppress compiler warnings in yy_fatal_error().
|
||||
|
@ -137,7 +142,9 @@ hyphen-bytes {hex2}(-{hex2})+
|
|||
|
||||
%%
|
||||
|
||||
[[:blank:]\n]+
|
||||
[[:blank:]\n]+ {
|
||||
update_location(yyextra, yytext);
|
||||
}
|
||||
|
||||
"(" return simple(TOKEN_LPAREN);
|
||||
")" return simple(TOKEN_RPAREN);
|
||||
|
@ -193,7 +200,8 @@ hyphen-bytes {hex2}(-{hex2})+
|
|||
}
|
||||
|
||||
<RANGE>[^],]+ {
|
||||
return set_lval_range_node(yyextra->dfw, TOKEN_RANGE_NODE, yytext);
|
||||
update_location(yyextra, yytext);
|
||||
return set_lval_range_node(yyextra, TOKEN_RANGE_NODE, yytext);
|
||||
}
|
||||
|
||||
<RANGE>"," {
|
||||
|
@ -206,7 +214,8 @@ hyphen-bytes {hex2}(-{hex2})+
|
|||
}
|
||||
|
||||
<RANGE><<EOF>> {
|
||||
dfilter_fail(yyextra->dfw, "The right bracket was missing from a slice.");
|
||||
update_location(yyextra, yytext);
|
||||
FAIL("The right bracket was missing from a slice.");
|
||||
return SCAN_FAILED;
|
||||
}
|
||||
|
||||
|
@ -218,7 +227,10 @@ hyphen-bytes {hex2}(-{hex2})+
|
|||
* See: https://westes.github.io/flex/manual/Start-Conditions.html
|
||||
*/
|
||||
BEGIN(DQUOTE);
|
||||
yyextra->quoted_string = g_string_new("");
|
||||
update_location(yyextra, yytext);
|
||||
yyextra->string_loc = yyextra->location;
|
||||
|
||||
yyextra->quoted_string = g_string_new("\"");
|
||||
|
||||
if (yytext[0] == 'r' || yytext[0] == 'R') {
|
||||
/*
|
||||
|
@ -239,22 +251,27 @@ hyphen-bytes {hex2}(-{hex2})+
|
|||
|
||||
<DQUOTE><<EOF>> {
|
||||
/* unterminated string */
|
||||
update_string_loc(yyextra, yytext);
|
||||
g_string_free(yyextra->quoted_string, TRUE);
|
||||
yyextra->quoted_string = NULL;
|
||||
dfilter_fail(yyextra->dfw, "The final quote was missing from a quoted string.");
|
||||
FAIL("The final quote was missing from a quoted string.");
|
||||
return SCAN_FAILED;
|
||||
}
|
||||
|
||||
<DQUOTE>\042 {
|
||||
/* end quote */
|
||||
BEGIN(INITIAL);
|
||||
set_lval_quoted_string(yyextra->dfw, TOKEN_STRING, yyextra->quoted_string);
|
||||
update_string_loc(yyextra, yytext);
|
||||
g_string_append_c(yyextra->quoted_string, '"');
|
||||
set_lval_quoted_string(yyextra, TOKEN_STRING, yyextra->quoted_string);
|
||||
yyextra->quoted_string = NULL;
|
||||
yyextra->string_loc.col_start = -1;
|
||||
return TOKEN_STRING;
|
||||
}
|
||||
|
||||
<DQUOTE>\\[0-7]{1,3} {
|
||||
/* octal sequence */
|
||||
update_string_loc(yyextra, yytext);
|
||||
if (yyextra->raw_string) {
|
||||
g_string_append(yyextra->quoted_string, yytext);
|
||||
}
|
||||
|
@ -264,13 +281,13 @@ hyphen-bytes {hex2}(-{hex2})+
|
|||
if (result == 0) {
|
||||
g_string_free(yyextra->quoted_string, TRUE);
|
||||
yyextra->quoted_string = NULL;
|
||||
dfilter_fail(yyextra->dfw, "%s (NUL byte) cannot be used with a regular string.", yytext);
|
||||
FAIL("%s (NUL byte) cannot be used with a regular string.", yytext);
|
||||
return SCAN_FAILED;
|
||||
}
|
||||
if (result > 0xff) {
|
||||
g_string_free(yyextra->quoted_string, TRUE);
|
||||
yyextra->quoted_string = NULL;
|
||||
dfilter_fail(yyextra->dfw, "%s is larger than 255.", yytext);
|
||||
FAIL("%s is larger than 255.", yytext);
|
||||
return SCAN_FAILED;
|
||||
}
|
||||
g_string_append_c(yyextra->quoted_string, (gchar) result);
|
||||
|
@ -283,6 +300,7 @@ hyphen-bytes {hex2}(-{hex2})+
|
|||
* C standard does not place a limit on the number of hex
|
||||
* digits after \x... but we do. \xNN can have 1 or two Ns, not more.
|
||||
*/
|
||||
update_string_loc(yyextra, yytext);
|
||||
if (yyextra->raw_string) {
|
||||
g_string_append(yyextra->quoted_string, yytext);
|
||||
}
|
||||
|
@ -292,7 +310,7 @@ hyphen-bytes {hex2}(-{hex2})+
|
|||
if (result == 0) {
|
||||
g_string_free(yyextra->quoted_string, TRUE);
|
||||
yyextra->quoted_string = NULL;
|
||||
dfilter_fail(yyextra->dfw, "%s (NUL byte) cannot be used with a regular string.", yytext);
|
||||
FAIL("%s (NUL byte) cannot be used with a regular string.", yytext);
|
||||
return SCAN_FAILED;
|
||||
}
|
||||
g_string_append_c(yyextra->quoted_string, (gchar) result);
|
||||
|
@ -302,10 +320,11 @@ hyphen-bytes {hex2}(-{hex2})+
|
|||
|
||||
<DQUOTE>\\. {
|
||||
/* escaped character */
|
||||
update_string_loc(yyextra, yytext);
|
||||
if (yyextra->raw_string) {
|
||||
g_string_append(yyextra->quoted_string, yytext);
|
||||
}
|
||||
else if (!append_escaped_char(yyextra->dfw, yyextra->quoted_string, yytext[1])) {
|
||||
else if (!append_escaped_char(yyextra, yyextra->quoted_string, yytext[1])) {
|
||||
g_string_free(yyextra->quoted_string, TRUE);
|
||||
yyextra->quoted_string = NULL;
|
||||
return SCAN_FAILED;
|
||||
|
@ -314,6 +333,7 @@ hyphen-bytes {hex2}(-{hex2})+
|
|||
|
||||
<DQUOTE>[^\\\042]+ {
|
||||
/* non-escaped string */
|
||||
update_string_loc(yyextra, yytext);
|
||||
g_string_append(yyextra->quoted_string, yytext);
|
||||
}
|
||||
|
||||
|
@ -321,33 +341,41 @@ hyphen-bytes {hex2}(-{hex2})+
|
|||
\047 {
|
||||
/* start quote of a quoted character value */
|
||||
BEGIN(SQUOTE);
|
||||
update_location(yyextra, yytext);
|
||||
yyextra->string_loc = yyextra->location;
|
||||
|
||||
yyextra->quoted_string = g_string_new("'");
|
||||
}
|
||||
|
||||
<SQUOTE><<EOF>> {
|
||||
/* unterminated character value */
|
||||
update_string_loc(yyextra, yytext);
|
||||
g_string_free(yyextra->quoted_string, TRUE);
|
||||
yyextra->quoted_string = NULL;
|
||||
dfilter_fail(yyextra->dfw, "The final quote was missing from a character constant.");
|
||||
FAIL("The final quote was missing from a character constant.");
|
||||
return SCAN_FAILED;
|
||||
}
|
||||
|
||||
<SQUOTE>\047 {
|
||||
/* end quote */
|
||||
BEGIN(INITIAL);
|
||||
update_string_loc(yyextra, yytext);
|
||||
g_string_append_c(yyextra->quoted_string, '\'');
|
||||
set_lval_charconst(yyextra->dfw, TOKEN_CHARCONST, yyextra->quoted_string);
|
||||
set_lval_charconst(yyextra, TOKEN_CHARCONST, yyextra->quoted_string);
|
||||
yyextra->quoted_string = NULL;
|
||||
yyextra->string_loc.col_start = -1;
|
||||
return TOKEN_CHARCONST;
|
||||
}
|
||||
|
||||
<SQUOTE>\\. {
|
||||
/* escaped character */
|
||||
update_string_loc(yyextra, yytext);
|
||||
g_string_append(yyextra->quoted_string, yytext);
|
||||
}
|
||||
|
||||
<SQUOTE>[^\\\047]+ {
|
||||
/* non-escaped string */
|
||||
update_string_loc(yyextra, yytext);
|
||||
g_string_append(yyextra->quoted_string, yytext);
|
||||
}
|
||||
|
||||
|
@ -356,60 +384,68 @@ hyphen-bytes {hex2}(-{hex2})+
|
|||
|
||||
{MacAddress}|{QuadMacAddress} {
|
||||
/* MAC Address. */
|
||||
return set_lval_str(TOKEN_UNPARSED, yytext);
|
||||
update_location(yyextra, yytext);
|
||||
return set_lval_str(yyextra, TOKEN_UNPARSED, yytext);
|
||||
}
|
||||
|
||||
{IPv4address}{v4-cidr-prefix}? {
|
||||
/* IPv4 with or without prefix. */
|
||||
return set_lval_str(TOKEN_UNPARSED, yytext);
|
||||
update_location(yyextra, yytext);
|
||||
return set_lval_str(yyextra, TOKEN_UNPARSED, yytext);
|
||||
}
|
||||
|
||||
{IPv6address}{v6-cidr-prefix}? {
|
||||
/* IPv6 with or without prefix. */
|
||||
return set_lval_str(TOKEN_UNPARSED, yytext);
|
||||
update_location(yyextra, yytext);
|
||||
return set_lval_str(yyextra, TOKEN_UNPARSED, yytext);
|
||||
}
|
||||
|
||||
:?({colon-bytes}|{dot-bytes}|{hyphen-bytes}) {
|
||||
/* Bytes. */
|
||||
update_location(yyextra, yytext);
|
||||
if (yytext[0] == ':')
|
||||
return set_lval_str(TOKEN_LITERAL, yytext); /* Keep leading colon. */
|
||||
return set_lval_str(TOKEN_UNPARSED, yytext);
|
||||
return set_lval_str(yyextra, TOKEN_LITERAL, yytext); /* Keep leading colon. */
|
||||
return set_lval_str(yyextra, TOKEN_UNPARSED, yytext);
|
||||
}
|
||||
|
||||
:[[:xdigit:]]+ {
|
||||
/* Numeric. */
|
||||
return set_lval_str(TOKEN_LITERAL, yytext + 1); /* Skip leading colon. */
|
||||
update_location(yyextra, yytext);
|
||||
return set_lval_str(yyextra, TOKEN_LITERAL, yytext + 1); /* Skip leading colon. */
|
||||
}
|
||||
|
||||
"<"[^>=]+">" {
|
||||
/* Literal in-between angle brackets (cannot be parsed as a protocol field). */
|
||||
/* Strip brackets. */
|
||||
update_location(yyextra, yytext);
|
||||
char *end = strchr(yytext, '>');
|
||||
*end = '\0';
|
||||
return set_lval_str(TOKEN_LITERAL, yytext + 1);
|
||||
return set_lval_str(yyextra, TOKEN_LITERAL, yytext + 1);
|
||||
}
|
||||
|
||||
\.?{Identifier} {
|
||||
/* Identifier or unparsed. */
|
||||
update_location(yyextra, yytext);
|
||||
if (yytext[0] == '.') {
|
||||
/* Skip leading dot. */
|
||||
return set_lval_field(yyextra->dfw, TOKEN_FIELD, yytext + 1);
|
||||
return set_lval_field(yyextra, TOKEN_FIELD, yytext + 1);
|
||||
}
|
||||
return set_lval_str(TOKEN_UNPARSED, yytext);
|
||||
return set_lval_str(yyextra, TOKEN_UNPARSED, yytext);
|
||||
}
|
||||
|
||||
"${"{Identifier}"}" {
|
||||
char *end = strchr(yytext, '}');
|
||||
*end = '\0';
|
||||
return set_lval_field(yyextra->dfw, TOKEN_REFERENCE, yytext + 2);
|
||||
return set_lval_field(yyextra, TOKEN_REFERENCE, yytext + 2);
|
||||
}
|
||||
|
||||
. {
|
||||
/* Default */
|
||||
update_location(yyextra, yytext);
|
||||
if (isprint_string(yytext))
|
||||
dfilter_fail(yyextra->dfw, "\"%s\" was unexpected in this context.", yytext);
|
||||
FAIL("\"%s\" was unexpected in this context.", yytext);
|
||||
else
|
||||
dfilter_fail(yyextra->dfw, "Non-printable ASCII characters may only appear inside double-quotes.");
|
||||
FAIL("Non-printable ASCII characters may only appear inside double-quotes.");
|
||||
return SCAN_FAILED;
|
||||
}
|
||||
|
||||
|
@ -421,15 +457,36 @@ hyphen-bytes {hex2}(-{hex2})+
|
|||
*/
|
||||
DIAG_ON_FLEX
|
||||
|
||||
static int
|
||||
set_lval_simple(int token, const char *token_value, sttype_id_t type_id)
|
||||
static void
|
||||
_update_location(df_scanner_state_t *state, size_t len)
|
||||
{
|
||||
stnode_init(df_lval, type_id, NULL, g_strdup(token_value));
|
||||
state->location.col_start += state->location.col_len;
|
||||
state->location.col_len = len;
|
||||
}
|
||||
|
||||
static void
|
||||
update_location(df_scanner_state_t *state, const char *text)
|
||||
{
|
||||
_update_location(state, strlen(text));
|
||||
}
|
||||
|
||||
static void
|
||||
update_string_loc(df_scanner_state_t *state, const char *text)
|
||||
{
|
||||
size_t len = strlen(text);
|
||||
state->string_loc.col_len += len;
|
||||
_update_location(state, len);
|
||||
}
|
||||
|
||||
static int
|
||||
set_lval_simple(df_scanner_state_t *state, int token, const char *token_value, sttype_id_t type_id)
|
||||
{
|
||||
stnode_init(df_lval, type_id, NULL, g_strdup(token_value), &state->location);
|
||||
return token;
|
||||
}
|
||||
|
||||
static int
|
||||
set_lval_str(int token, const char *token_value)
|
||||
set_lval_str(df_scanner_state_t *state, int token, const char *token_value)
|
||||
{
|
||||
sttype_id_t type_id;
|
||||
|
||||
|
@ -443,37 +500,42 @@ set_lval_str(int token, const char *token_value)
|
|||
default:
|
||||
ws_assert_not_reached();
|
||||
}
|
||||
stnode_init(df_lval, type_id, g_strdup(token_value), g_strdup(token_value));
|
||||
stnode_init(df_lval, type_id, g_strdup(token_value), g_strdup(token_value), &state->location);
|
||||
return token;
|
||||
}
|
||||
|
||||
static int
|
||||
set_lval_quoted_string(dfwork_t *dfw _U_, int token, GString *quoted_string)
|
||||
set_lval_quoted_string(df_scanner_state_t *state, int token, GString *quoted_string)
|
||||
{
|
||||
ws_assert(token == TOKEN_STRING);
|
||||
char *token_value = g_string_free(quoted_string, FALSE);
|
||||
|
||||
stnode_init(df_lval, STTYPE_STRING, g_string_free(quoted_string, FALSE), NULL);
|
||||
/* Strip start and end quote. */
|
||||
char *data = g_strndup(token_value + 1, strlen(token_value + 1) - 1);
|
||||
|
||||
stnode_init(df_lval, STTYPE_STRING, data, token_value, &state->string_loc);
|
||||
return token;
|
||||
}
|
||||
|
||||
static int
|
||||
set_lval_charconst(dfwork_t *dfw, int token, GString *quoted_string)
|
||||
set_lval_charconst(df_scanner_state_t *state, int token, GString *quoted_string)
|
||||
{
|
||||
ws_assert(token == TOKEN_CHARCONST);
|
||||
unsigned long number;
|
||||
gboolean ok;
|
||||
|
||||
ok = parse_charconst(dfw, quoted_string->str, &number);
|
||||
g_string_free(quoted_string, TRUE);
|
||||
char *token_value = g_string_free(quoted_string, FALSE);
|
||||
ok = parse_charconst(state, token_value, &number);
|
||||
if (!ok) {
|
||||
g_free(token_value);
|
||||
return SCAN_FAILED;
|
||||
}
|
||||
stnode_init(df_lval, STTYPE_CHARCONST, g_memdup2(&number, sizeof(number)), NULL);
|
||||
stnode_init(df_lval, STTYPE_CHARCONST, g_memdup2(&number, sizeof(number)), token_value, &state->string_loc);
|
||||
return token;
|
||||
}
|
||||
|
||||
static int
|
||||
set_lval_field(dfwork_t *dfw, int token, const char *token_value)
|
||||
set_lval_field(df_scanner_state_t *state, int token, const char *token_value)
|
||||
{
|
||||
sttype_id_t type_id;
|
||||
header_field_info *hfinfo;
|
||||
|
@ -489,16 +551,16 @@ set_lval_field(dfwork_t *dfw, int token, const char *token_value)
|
|||
ws_assert_not_reached();
|
||||
}
|
||||
|
||||
hfinfo = dfilter_resolve_unparsed(dfw, token_value);
|
||||
hfinfo = dfilter_resolve_unparsed(state->dfw, token_value);
|
||||
if (hfinfo == NULL) {
|
||||
dfilter_fail(dfw, "\"%s\" is not a valid protocol or protocol field.", token_value);
|
||||
dfilter_fail(state->dfw, &state->location, "\"%s\" is not a valid protocol or protocol field.", token_value);
|
||||
}
|
||||
stnode_init(df_lval, type_id, hfinfo, g_strdup(token_value));
|
||||
stnode_init(df_lval, type_id, hfinfo, g_strdup(token_value), &state->location);
|
||||
return token;
|
||||
}
|
||||
|
||||
static int
|
||||
set_lval_range_node(dfwork_t *dfw, int token, const char *token_value)
|
||||
set_lval_range_node(df_scanner_state_t *state, int token, const char *token_value)
|
||||
{
|
||||
ws_assert(token == TOKEN_RANGE_NODE);
|
||||
char *err = NULL;
|
||||
|
@ -506,16 +568,16 @@ set_lval_range_node(dfwork_t *dfw, int token, const char *token_value)
|
|||
|
||||
range = drange_node_from_str(token_value, &err);
|
||||
if (err != NULL) {
|
||||
dfilter_fail(dfw, "%s", err);
|
||||
dfilter_fail(state->dfw, &state->location, "%s", err);
|
||||
g_free(err);
|
||||
return SCAN_FAILED;
|
||||
}
|
||||
stnode_init(df_lval, STTYPE_RANGE_NODE, range, NULL);
|
||||
stnode_init(df_lval, STTYPE_RANGE_NODE, range, g_strdup(token_value), &state->location);
|
||||
return token;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
append_escaped_char(dfwork_t *dfw, GString *str, char c)
|
||||
append_escaped_char(df_scanner_state_t *state, GString *str, char c)
|
||||
{
|
||||
switch (c) {
|
||||
case 'a':
|
||||
|
@ -544,7 +606,8 @@ append_escaped_char(dfwork_t *dfw, GString *str, char c)
|
|||
case '\"':
|
||||
break;
|
||||
default:
|
||||
dfilter_fail(dfw, "\\%c is not a valid character escape sequence", c);
|
||||
dfilter_fail(state->dfw, &state->location,
|
||||
"\\%c is not a valid character escape sequence", c);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
|
@ -553,14 +616,14 @@ append_escaped_char(dfwork_t *dfw, GString *str, char c)
|
|||
}
|
||||
|
||||
static gboolean
|
||||
parse_charconst(dfwork_t *dfw, const char *s, unsigned long *valuep)
|
||||
parse_charconst(df_scanner_state_t *state, const char *s, unsigned long *valuep)
|
||||
{
|
||||
const char *cp;
|
||||
unsigned long value;
|
||||
|
||||
cp = s + 1; /* skip the leading ' */
|
||||
if (*cp == '\'') {
|
||||
dfilter_fail(dfw, "Empty character constant.");
|
||||
dfilter_fail(state->dfw, &state->string_loc, "Empty character constant.");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
|
@ -576,7 +639,7 @@ parse_charconst(dfwork_t *dfw, const char *s, unsigned long *valuep)
|
|||
switch (*cp) {
|
||||
|
||||
case '\0':
|
||||
dfilter_fail(dfw, "%s isn't a valid character constant.", s);
|
||||
dfilter_fail(state->dfw, &state->string_loc, "%s isn't a valid character constant.", s);
|
||||
return FALSE;
|
||||
|
||||
case 'a':
|
||||
|
@ -628,7 +691,7 @@ parse_charconst(dfwork_t *dfw, const char *s, unsigned long *valuep)
|
|||
else if (*cp >= 'a' && *cp <= 'f')
|
||||
value = 10 + (*cp - 'a');
|
||||
else {
|
||||
dfilter_fail(dfw, "%s isn't a valid character constant.", s);
|
||||
dfilter_fail(state->dfw, &state->string_loc, "%s isn't a valid character constant.", s);
|
||||
return FALSE;
|
||||
}
|
||||
cp++;
|
||||
|
@ -641,7 +704,7 @@ parse_charconst(dfwork_t *dfw, const char *s, unsigned long *valuep)
|
|||
else if (*cp >= 'a' && *cp <= 'f')
|
||||
value |= 10 + (*cp - 'a');
|
||||
else {
|
||||
dfilter_fail(dfw, "%s isn't a valid character constant.", s);
|
||||
dfilter_fail(state->dfw, &state->string_loc, "%s isn't a valid character constant.", s);
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
|
@ -652,7 +715,7 @@ parse_charconst(dfwork_t *dfw, const char *s, unsigned long *valuep)
|
|||
if (*cp >= '0' && *cp <= '7')
|
||||
value = *cp - '0';
|
||||
else {
|
||||
dfilter_fail(dfw, "%s isn't a valid character constant.", s);
|
||||
dfilter_fail(state->dfw, &state->string_loc, "%s isn't a valid character constant.", s);
|
||||
return FALSE;
|
||||
}
|
||||
if (*(cp + 1) != '\'') {
|
||||
|
@ -661,7 +724,7 @@ parse_charconst(dfwork_t *dfw, const char *s, unsigned long *valuep)
|
|||
if (*cp >= '0' && *cp <= '7')
|
||||
value |= *cp - '0';
|
||||
else {
|
||||
dfilter_fail(dfw, "%s isn't a valid character constant.", s);
|
||||
dfilter_fail(state->dfw, &state->string_loc, "%s isn't a valid character constant.", s);
|
||||
return FALSE;
|
||||
}
|
||||
if (*(cp + 1) != '\'') {
|
||||
|
@ -670,26 +733,26 @@ parse_charconst(dfwork_t *dfw, const char *s, unsigned long *valuep)
|
|||
if (*cp >= '0' && *cp <= '7')
|
||||
value |= *cp - '0';
|
||||
else {
|
||||
dfilter_fail(dfw, "%s isn't a valid character constant.", s);
|
||||
dfilter_fail(state->dfw, &state->string_loc, "%s isn't a valid character constant.", s);
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (value > 0xFF) {
|
||||
dfilter_fail(dfw, "%s is too large to be a valid character constant.", s);
|
||||
dfilter_fail(state->dfw, &state->string_loc, "%s is too large to be a valid character constant.", s);
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
value = *cp;
|
||||
if (!g_ascii_isprint(value)) {
|
||||
dfilter_fail(dfw, "Non-printable value '0x%02lx' in character constant.", value);
|
||||
dfilter_fail(state->dfw, &state->string_loc, "Non-printable value '0x%02lx' in character constant.", value);
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
cp++;
|
||||
if ((*cp != '\'') || (*(cp + 1) != '\0')){
|
||||
dfilter_fail(dfw, "%s is too long to be a valid character constant.", s);
|
||||
dfilter_fail(state->dfw, &state->string_loc, "%s is too long to be a valid character constant.", s);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
|
|
|
@ -29,10 +29,11 @@
|
|||
#include <ftypes/ftypes.h>
|
||||
|
||||
|
||||
#define FAIL(dfw, ...) \
|
||||
#define FAIL(dfw, node, ...) \
|
||||
do { \
|
||||
ws_noisy("Semantic check failed here."); \
|
||||
dfilter_fail_throw(dfw, TypeError, __VA_ARGS__); \
|
||||
dfilter_fail_throw(dfw, stnode_location(node), \
|
||||
TypeError, __VA_ARGS__); \
|
||||
} while (0)
|
||||
|
||||
static void
|
||||
|
@ -181,8 +182,11 @@ dfilter_fvalue_from_literal(dfwork_t *dfw, ftenum_t ftype, stnode_t *st,
|
|||
dfw->error_message = NULL;
|
||||
}
|
||||
}
|
||||
if (fv == NULL)
|
||||
if (fv == NULL) {
|
||||
dfw_set_error_location(dfw, stnode_location(st));
|
||||
THROW(TypeError);
|
||||
}
|
||||
|
||||
return fv;
|
||||
}
|
||||
|
||||
|
@ -222,6 +226,7 @@ dfilter_fvalue_from_unparsed(dfwork_t *dfw, ftenum_t ftype, stnode_t *st,
|
|||
if (hfinfo == NULL) {
|
||||
/* This node is neither a valid fvalue nor a valid field. */
|
||||
/* The parse failed. Error message is already set. */
|
||||
dfw_set_error_location(dfw, stnode_location(st));
|
||||
THROW(TypeError);
|
||||
}
|
||||
|
||||
|
@ -258,8 +263,11 @@ dfilter_fvalue_from_string(dfwork_t *dfw, ftenum_t ftype, stnode_t *st,
|
|||
dfw->error_message = NULL;
|
||||
}
|
||||
}
|
||||
if (fv == NULL)
|
||||
if (fv == NULL) {
|
||||
dfw_set_error_location(dfw, stnode_location(st));
|
||||
THROW(TypeError);
|
||||
}
|
||||
|
||||
return fv;
|
||||
}
|
||||
|
||||
|
@ -386,7 +394,7 @@ mk_fvalue_from_val_string(dfwork_t *dfw, header_field_info *hfinfo, const char *
|
|||
*/
|
||||
g_free(dfw->error_message);
|
||||
dfw->error_message = NULL;
|
||||
dfilter_fail(dfw, "\"%s\" cannot be found among the possible values for %s.",
|
||||
dfilter_fail(dfw, NULL, "\"%s\" cannot be found among the possible values for %s.",
|
||||
s, hfinfo->abbrev);
|
||||
return NULL;
|
||||
}
|
||||
|
@ -394,7 +402,7 @@ mk_fvalue_from_val_string(dfwork_t *dfw, header_field_info *hfinfo, const char *
|
|||
|
||||
/* Do val_strings exist? */
|
||||
if (!hfinfo->strings) {
|
||||
dfilter_fail(dfw, "%s cannot accept strings as values.",
|
||||
dfilter_fail(dfw, NULL, "%s cannot accept strings as values.",
|
||||
hfinfo->abbrev);
|
||||
return NULL;
|
||||
}
|
||||
|
@ -406,7 +414,7 @@ mk_fvalue_from_val_string(dfwork_t *dfw, header_field_info *hfinfo, const char *
|
|||
dfw->error_message = NULL;
|
||||
|
||||
if (hfinfo->display & BASE_RANGE_STRING) {
|
||||
dfilter_fail(dfw, "\"%s\" cannot accept [range] strings as values.",
|
||||
dfilter_fail(dfw, NULL, "\"%s\" cannot accept [range] strings as values.",
|
||||
hfinfo->abbrev);
|
||||
}
|
||||
else if (hfinfo->display & BASE_VAL64_STRING) {
|
||||
|
@ -418,7 +426,7 @@ mk_fvalue_from_val_string(dfwork_t *dfw, header_field_info *hfinfo, const char *
|
|||
}
|
||||
vals++;
|
||||
}
|
||||
dfilter_fail(dfw, "\"%s\" cannot be found among the possible values for %s.",
|
||||
dfilter_fail(dfw, NULL, "\"%s\" cannot be found among the possible values for %s.",
|
||||
s, hfinfo->abbrev);
|
||||
}
|
||||
else if (hfinfo->display == BASE_CUSTOM) {
|
||||
|
@ -428,7 +436,7 @@ mk_fvalue_from_val_string(dfwork_t *dfw, header_field_info *hfinfo, const char *
|
|||
* integer, we have the string they're trying to match.
|
||||
* -><-
|
||||
*/
|
||||
dfilter_fail(dfw, "\"%s\" cannot accept [custom] strings as values.",
|
||||
dfilter_fail(dfw, NULL, "\"%s\" cannot accept [custom] strings as values.",
|
||||
hfinfo->abbrev);
|
||||
}
|
||||
else {
|
||||
|
@ -442,7 +450,7 @@ mk_fvalue_from_val_string(dfwork_t *dfw, header_field_info *hfinfo, const char *
|
|||
}
|
||||
vals++;
|
||||
}
|
||||
dfilter_fail(dfw, "\"%s\" cannot be found among the possible values for %s.",
|
||||
dfilter_fail(dfw, NULL, "\"%s\" cannot be found among the possible values for %s.",
|
||||
s, hfinfo->abbrev);
|
||||
}
|
||||
return NULL;
|
||||
|
@ -527,7 +535,7 @@ check_exists(dfwork_t *dfw, stnode_t *st_arg1)
|
|||
case STTYPE_STRING:
|
||||
case STTYPE_LITERAL:
|
||||
case STTYPE_CHARCONST:
|
||||
FAIL(dfw, "%s is neither a field nor a protocol name.",
|
||||
FAIL(dfw, st_arg1, "%s is neither a field nor a protocol name.",
|
||||
stnode_todisplay(st_arg1));
|
||||
break;
|
||||
|
||||
|
@ -538,13 +546,13 @@ check_exists(dfwork_t *dfw, stnode_t *st_arg1)
|
|||
* has at least 2 bytes starting at an offset of
|
||||
* 3"?
|
||||
*/
|
||||
FAIL(dfw, "You cannot test whether a range is present.");
|
||||
FAIL(dfw, st_arg1, "You cannot test whether a range is present.");
|
||||
break;
|
||||
|
||||
case STTYPE_FUNCTION:
|
||||
/* XXX - Maybe we should change functions so they can return fields,
|
||||
* in which case the 'exist' should be fine. */
|
||||
FAIL(dfw, "You cannot test whether a function is present.");
|
||||
FAIL(dfw, st_arg1, "You cannot test whether a function is present.");
|
||||
break;
|
||||
|
||||
case STTYPE_SET:
|
||||
|
@ -577,7 +585,7 @@ check_drange_sanity(dfwork_t *dfw, stnode_t *st)
|
|||
ftype1 = hfinfo1->type;
|
||||
|
||||
if (!ftype_can_slice(ftype1)) {
|
||||
FAIL(dfw, "\"%s\" is a %s and cannot be sliced into a sequence of bytes.",
|
||||
FAIL(dfw, entity1, "\"%s\" is a %s and cannot be sliced into a sequence of bytes.",
|
||||
hfinfo1->abbrev, ftype_pretty_name(ftype1));
|
||||
}
|
||||
} else if (stnode_type_id(entity1) == STTYPE_FUNCTION) {
|
||||
|
@ -585,7 +593,7 @@ check_drange_sanity(dfwork_t *dfw, stnode_t *st)
|
|||
ftype1 = funcdef->retval_ftype;
|
||||
|
||||
if (!ftype_can_slice(ftype1)) {
|
||||
FAIL(dfw, "Return value of function \"%s\" is a %s and cannot be converted into a sequence of bytes.",
|
||||
FAIL(dfw, entity1, "Return value of function \"%s\" is a %s and cannot be converted into a sequence of bytes.",
|
||||
funcdef->name, ftype_pretty_name(ftype1));
|
||||
}
|
||||
|
||||
|
@ -594,7 +602,7 @@ check_drange_sanity(dfwork_t *dfw, stnode_t *st)
|
|||
/* Should this be rejected instead? */
|
||||
check_drange_sanity(dfw, entity1);
|
||||
} else {
|
||||
FAIL(dfw, "Range is not supported for entity %s",
|
||||
FAIL(dfw, entity1, "Range is not supported for entity %s",
|
||||
stnode_todisplay(entity1));
|
||||
}
|
||||
}
|
||||
|
@ -629,10 +637,10 @@ check_function(dfwork_t *dfw, stnode_t *st_node)
|
|||
nparams = g_slist_length(params);
|
||||
|
||||
if (nparams < funcdef->min_nargs) {
|
||||
FAIL(dfw, "Function %s needs at least %u arguments.",
|
||||
FAIL(dfw, st_node, "Function %s needs at least %u arguments.",
|
||||
funcdef->name, funcdef->min_nargs);
|
||||
} else if (nparams > funcdef->max_nargs) {
|
||||
FAIL(dfw, "Function %s can only accept %u arguments.",
|
||||
FAIL(dfw, st_node, "Function %s can only accept %u arguments.",
|
||||
funcdef->name, funcdef->max_nargs);
|
||||
}
|
||||
|
||||
|
@ -654,8 +662,11 @@ dfilter_fvalue_from_charconst(dfwork_t *dfw, ftenum_t ftype, stnode_t *st)
|
|||
|
||||
fvalue = fvalue_from_charconst(ftype, *nump,
|
||||
dfw->error_message == NULL ? &dfw->error_message : NULL);
|
||||
if (fvalue == NULL)
|
||||
|
||||
if (fvalue == NULL) {
|
||||
dfw_set_error_location(dfw, stnode_location(st));
|
||||
THROW(TypeError);
|
||||
}
|
||||
|
||||
return fvalue;
|
||||
}
|
||||
|
@ -683,7 +694,7 @@ again:
|
|||
ftype1 = hfinfo1->type;
|
||||
|
||||
if (!can_func(ftype1)) {
|
||||
FAIL(dfw, "%s (type=%s) cannot participate in %s comparison.",
|
||||
FAIL(dfw, st_arg1, "%s (type=%s) cannot participate in %s comparison.",
|
||||
hfinfo1->abbrev, ftype_pretty_name(ftype1),
|
||||
stnode_todisplay(st_node));
|
||||
}
|
||||
|
@ -693,13 +704,13 @@ again:
|
|||
ftype2 = hfinfo2->type;
|
||||
|
||||
if (!compatible_ftypes(ftype1, ftype2)) {
|
||||
FAIL(dfw, "%s and %s are not of compatible types.",
|
||||
FAIL(dfw, st_arg2, "%s and %s are not of compatible types.",
|
||||
hfinfo1->abbrev, hfinfo2->abbrev);
|
||||
}
|
||||
/* Do this check even though you'd think that if
|
||||
* they're compatible, then can_func() would pass. */
|
||||
if (!can_func(ftype2)) {
|
||||
FAIL(dfw, "%s (type=%s) cannot participate in specified comparison.",
|
||||
FAIL(dfw, st_arg2, "%s (type=%s) cannot participate in specified comparison.",
|
||||
hfinfo2->abbrev, ftype_pretty_name(ftype2));
|
||||
}
|
||||
}
|
||||
|
@ -735,7 +746,7 @@ again:
|
|||
check_drange_sanity(dfw, st_arg2);
|
||||
if (!is_bytes_type(ftype1)) {
|
||||
if (!ftype_can_slice(ftype1)) {
|
||||
FAIL(dfw, "\"%s\" is a %s and cannot be converted into a sequence of bytes.",
|
||||
FAIL(dfw, st_arg1, "\"%s\" is a %s and cannot be converted into a sequence of bytes.",
|
||||
hfinfo1->abbrev,
|
||||
ftype_pretty_name(ftype1));
|
||||
}
|
||||
|
@ -749,13 +760,13 @@ again:
|
|||
ftype2 = funcdef->retval_ftype;
|
||||
|
||||
if (!compatible_ftypes(ftype1, ftype2)) {
|
||||
FAIL(dfw, "%s (type=%s) and return value of %s() (type=%s) are not of compatible types.",
|
||||
FAIL(dfw, st_arg2, "%s (type=%s) and return value of %s() (type=%s) are not of compatible types.",
|
||||
hfinfo1->abbrev, ftype_pretty_name(ftype1),
|
||||
funcdef->name, ftype_pretty_name(ftype2));
|
||||
}
|
||||
|
||||
if (!can_func(ftype2)) {
|
||||
FAIL(dfw, "return value of %s() (type=%s) cannot participate in specified comparison.",
|
||||
FAIL(dfw, st_arg2, "return value of %s() (type=%s) cannot participate in specified comparison.",
|
||||
funcdef->name, ftype_pretty_name(ftype2));
|
||||
}
|
||||
|
||||
|
@ -768,12 +779,12 @@ again:
|
|||
ftype2 = check_arithmetic_expr(dfw, st_arg2, ftype1);
|
||||
|
||||
if (!compatible_ftypes(ftype1, ftype2)) {
|
||||
FAIL(dfw, "%s and %s are not of compatible types.",
|
||||
FAIL(dfw, st_arg2, "%s and %s are not of compatible types.",
|
||||
stnode_todisplay(st_arg1), stnode_todisplay(st_arg2));
|
||||
}
|
||||
|
||||
if (!can_func(ftype2)) {
|
||||
FAIL(dfw, "%s (type=%s) cannot participate in specified comparison.",
|
||||
FAIL(dfw, st_arg2, "%s (type=%s) cannot participate in specified comparison.",
|
||||
stnode_todisplay(st_arg2), ftype_pretty_name(ftype2));
|
||||
}
|
||||
}
|
||||
|
@ -807,7 +818,7 @@ again:
|
|||
|
||||
if (!is_bytes_type(ftype2)) {
|
||||
if (!ftype_can_slice(ftype2)) {
|
||||
FAIL(dfw, "\"%s\" is a %s and cannot be converted into a sequence of bytes.",
|
||||
FAIL(dfw, st_arg2, "\"%s\" is a %s and cannot be converted into a sequence of bytes.",
|
||||
hfinfo2->abbrev,
|
||||
ftype_pretty_name(ftype2));
|
||||
}
|
||||
|
@ -845,7 +856,7 @@ again:
|
|||
|
||||
if (!is_bytes_type(ftype2)) {
|
||||
if (!ftype_can_slice(ftype2)) {
|
||||
FAIL(dfw, "Return value of function \"%s\" is a %s and cannot be converted into a sequence of bytes.",
|
||||
FAIL(dfw, st_arg2, "Return value of function \"%s\" is a %s and cannot be converted into a sequence of bytes.",
|
||||
funcdef->name,
|
||||
ftype_pretty_name(ftype2));
|
||||
}
|
||||
|
@ -863,12 +874,12 @@ again:
|
|||
ftype2 = check_arithmetic_expr(dfw, st_arg2, FT_BYTES);
|
||||
|
||||
if (!compatible_ftypes(FT_BYTES, ftype2)) {
|
||||
FAIL(dfw, "%s and %s are not of compatible types.",
|
||||
FAIL(dfw, st_arg2, "%s and %s are not of compatible types.",
|
||||
stnode_todisplay(st_arg1), stnode_todisplay(st_arg2));
|
||||
}
|
||||
|
||||
if (!can_func(ftype2)) {
|
||||
FAIL(dfw, "%s (type=%s) cannot participate in specified comparison.",
|
||||
FAIL(dfw, st_arg2, "%s (type=%s) cannot participate in specified comparison.",
|
||||
stnode_todisplay(st_arg2), ftype_pretty_name(ftype2));
|
||||
}
|
||||
}
|
||||
|
@ -900,7 +911,7 @@ check_relation_LHS_FUNCTION(dfwork_t *dfw, test_op_t st_op,
|
|||
ftype1 = funcdef->retval_ftype;
|
||||
|
||||
if (!can_func(ftype1)) {
|
||||
FAIL(dfw, "Function %s (type=%s) cannot participate in %s comparison.",
|
||||
FAIL(dfw, st_arg1, "Function %s (type=%s) cannot participate in %s comparison.",
|
||||
funcdef->name, ftype_pretty_name(ftype1),
|
||||
stnode_todisplay(st_node));
|
||||
}
|
||||
|
@ -913,13 +924,13 @@ again:
|
|||
ftype2 = hfinfo2->type;
|
||||
|
||||
if (!compatible_ftypes(ftype1, ftype2)) {
|
||||
FAIL(dfw, "Function %s and %s are not of compatible types.",
|
||||
FAIL(dfw, st_arg2, "Function %s and %s are not of compatible types.",
|
||||
funcdef->name, hfinfo2->abbrev);
|
||||
}
|
||||
/* Do this check even though you'd think that if
|
||||
* they're compatible, then can_func() would pass. */
|
||||
if (!can_func(ftype2)) {
|
||||
FAIL(dfw, "%s (type=%s) cannot participate in specified comparison.",
|
||||
FAIL(dfw, st_arg2, "%s (type=%s) cannot participate in specified comparison.",
|
||||
hfinfo2->abbrev, ftype_pretty_name(ftype2));
|
||||
}
|
||||
}
|
||||
|
@ -947,7 +958,7 @@ again:
|
|||
check_drange_sanity(dfw, st_arg2);
|
||||
if (!is_bytes_type(ftype1)) {
|
||||
if (!ftype_can_slice(ftype1)) {
|
||||
FAIL(dfw, "Function \"%s\" is a %s and cannot be converted into a sequence of bytes.",
|
||||
FAIL(dfw, st_arg1, "Function \"%s\" is a %s and cannot be converted into a sequence of bytes.",
|
||||
funcdef->name,
|
||||
ftype_pretty_name(ftype1));
|
||||
}
|
||||
|
@ -961,14 +972,14 @@ again:
|
|||
ftype2 = funcdef2->retval_ftype;
|
||||
|
||||
if (!compatible_ftypes(ftype1, ftype2)) {
|
||||
FAIL(dfw, "Return values of function %s (type=%s) and function %s (type=%s) are not of compatible types.",
|
||||
FAIL(dfw, st_arg2, "Return values of function %s (type=%s) and function %s (type=%s) are not of compatible types.",
|
||||
funcdef->name, ftype_pretty_name(ftype1), funcdef2->name, ftype_pretty_name(ftype2));
|
||||
}
|
||||
|
||||
/* Do this check even though you'd think that if
|
||||
* they're compatible, then can_func() would pass. */
|
||||
if (!can_func(ftype2)) {
|
||||
FAIL(dfw, "Return value of %s (type=%s) cannot participate in specified comparison.",
|
||||
FAIL(dfw, st_arg2, "Return value of %s (type=%s) cannot participate in specified comparison.",
|
||||
funcdef2->name, ftype_pretty_name(ftype2));
|
||||
}
|
||||
|
||||
|
@ -981,12 +992,12 @@ again:
|
|||
ftype2 = check_arithmetic_expr(dfw, st_arg2, ftype1);
|
||||
|
||||
if (!compatible_ftypes(ftype1, ftype2)) {
|
||||
FAIL(dfw, "%s and %s are not of compatible types.",
|
||||
FAIL(dfw, st_arg2, "%s and %s are not of compatible types.",
|
||||
stnode_todisplay(st_arg1), stnode_todisplay(st_arg2));
|
||||
}
|
||||
|
||||
if (!can_func(ftype2)) {
|
||||
FAIL(dfw, "%s (type=%s) cannot participate in specified comparison.",
|
||||
FAIL(dfw, st_arg2, "%s (type=%s) cannot participate in specified comparison.",
|
||||
stnode_todisplay(st_arg2), ftype_pretty_name(ftype2));
|
||||
}
|
||||
}
|
||||
|
@ -1056,7 +1067,7 @@ check_relation(dfwork_t *dfw, test_op_t st_op,
|
|||
allow_partial_value, st_node, st_arg1, st_arg2);
|
||||
break;
|
||||
default:
|
||||
FAIL(dfw, "Left side of %s expression must be a field or function, not %s.",
|
||||
FAIL(dfw, st_arg1, "Left side of %s expression must be a field or function, not %s.",
|
||||
stnode_todisplay(st_node), stnode_todisplay(st_arg1));
|
||||
}
|
||||
}
|
||||
|
@ -1084,7 +1095,7 @@ check_relation_contains(dfwork_t *dfw, stnode_t *st_node,
|
|||
TRUE, st_node, st_arg1, st_arg2);
|
||||
break;
|
||||
default:
|
||||
FAIL(dfw, "Left side of %s expression must be a field or function, not %s.",
|
||||
FAIL(dfw, st_arg1, "Left side of %s expression must be a field or function, not %s.",
|
||||
stnode_todisplay(st_node), stnode_todisplay(st_arg1));
|
||||
}
|
||||
}
|
||||
|
@ -1103,7 +1114,7 @@ check_relation_matches(dfwork_t *dfw, stnode_t *st_node,
|
|||
resolve_unparsed(dfw, st_arg1);
|
||||
|
||||
if (stnode_type_id(st_arg2) != STTYPE_STRING) {
|
||||
FAIL(dfw, "Matches requires a double quoted string on the right side.");
|
||||
FAIL(dfw, st_arg2, "Matches requires a double quoted string on the right side.");
|
||||
}
|
||||
|
||||
patt = stnode_data(st_arg2);
|
||||
|
@ -1111,7 +1122,7 @@ check_relation_matches(dfwork_t *dfw, stnode_t *st_node,
|
|||
|
||||
pcre = ws_regex_compile(patt, &errmsg);
|
||||
if (errmsg) {
|
||||
dfilter_fail(dfw, "Regex compilation error: %s.", errmsg);
|
||||
dfilter_fail(dfw, NULL, "Regex compilation error: %s.", errmsg);
|
||||
g_free(errmsg);
|
||||
THROW(TypeError);
|
||||
}
|
||||
|
@ -1133,7 +1144,7 @@ check_relation_matches(dfwork_t *dfw, stnode_t *st_node,
|
|||
TRUE, st_node, st_arg1, st_arg2);
|
||||
break;
|
||||
default:
|
||||
FAIL(dfw, "Left side of %s expression must be a field or function, not %s.",
|
||||
FAIL(dfw, st_arg1, "Left side of %s expression must be a field or function, not %s.",
|
||||
stnode_todisplay(st_node), stnode_todisplay(st_arg1));
|
||||
}
|
||||
}
|
||||
|
@ -1150,7 +1161,7 @@ check_relation_in(dfwork_t *dfw, stnode_t *st_node _U_,
|
|||
resolve_unparsed(dfw, st_arg1);
|
||||
|
||||
if (stnode_type_id(st_arg1) != STTYPE_FIELD) {
|
||||
FAIL(dfw, "Only a field may be tested for membership in a set.");
|
||||
FAIL(dfw, st_arg1, "Only a field may be tested for membership in a set.");
|
||||
}
|
||||
/* Checked in the grammar parser. */
|
||||
ws_assert(stnode_type_id(st_arg2) == STTYPE_SET);
|
||||
|
@ -1165,7 +1176,7 @@ check_relation_in(dfwork_t *dfw, stnode_t *st_node _U_,
|
|||
|
||||
/* Don't let a range on the RHS affect the LHS field. */
|
||||
if (stnode_type_id(node_left) == STTYPE_RANGE) {
|
||||
FAIL(dfw, "A range may not appear inside a set.");
|
||||
FAIL(dfw, node_left, "A range may not appear inside a set.");
|
||||
break;
|
||||
}
|
||||
|
||||
|
@ -1279,7 +1290,7 @@ check_arithmetic_entity(dfwork_t *dfw, stnode_t *st_arg, ftenum_t lhs_ftype)
|
|||
ftype = fvalue_type_ftenum(stnode_data(st_arg));
|
||||
}
|
||||
else {
|
||||
FAIL(dfw, "%s is not a valid arithmetic operand",
|
||||
FAIL(dfw, st_arg, "%s is not a valid arithmetic operand.",
|
||||
stnode_todisplay(st_arg));
|
||||
}
|
||||
|
||||
|
@ -1305,7 +1316,7 @@ check_arithmetic_expr(dfwork_t *dfw, stnode_t *st_node, ftenum_t lhs_ftype)
|
|||
|
||||
/* On the LHS we require a field-like value as the first term. */
|
||||
if (lhs_ftype == FT_NONE && node_is_constant(st_arg1)) {
|
||||
FAIL(dfw, "Constant arithmetic expression on the LHS is invalid.");
|
||||
FAIL(dfw, st_arg1, "Constant arithmetic expression on the LHS is invalid.");
|
||||
}
|
||||
|
||||
if (st_op == OP_UNARY_MINUS) {
|
||||
|
@ -1315,7 +1326,8 @@ check_arithmetic_expr(dfwork_t *dfw, stnode_t *st_node, ftenum_t lhs_ftype)
|
|||
char *err_msg;
|
||||
fvalue_t *new_fv = fvalue_unary_minus(stnode_data(st_arg1), &err_msg);
|
||||
if (new_fv == NULL) {
|
||||
dfilter_fail(dfw, "%s: %s", stnode_todisplay(st_arg1), err_msg);
|
||||
dfilter_fail(dfw, stnode_location(st_arg1),
|
||||
"%s: %s", stnode_todisplay(st_arg1), err_msg);
|
||||
g_free(err_msg);
|
||||
THROW(TypeError);
|
||||
}
|
||||
|
@ -1352,16 +1364,16 @@ check_arithmetic_expr(dfwork_t *dfw, stnode_t *st_node, ftenum_t lhs_ftype)
|
|||
}
|
||||
|
||||
if (!can_func(ftype1)) {
|
||||
FAIL(dfw, "%s cannot %s.",
|
||||
FAIL(dfw, st_arg1, "%s cannot %s.",
|
||||
ftype_name(ftype1), stnode_todisplay(st_node));
|
||||
}
|
||||
if (!can_func(ftype2)) {
|
||||
FAIL(dfw, "%s cannot %s.",
|
||||
FAIL(dfw, st_arg2, "%s cannot %s.",
|
||||
ftype_name(ftype2), stnode_todisplay(st_node));
|
||||
}
|
||||
|
||||
if (!compatible_ftypes(ftype1, ftype2)) {
|
||||
FAIL(dfw, "%s and %s are not type compatible.",
|
||||
FAIL(dfw, st_arg2, "%s and %s are not type compatible.",
|
||||
stnode_todisplay(st_arg1), stnode_todisplay(st_arg2));
|
||||
}
|
||||
|
||||
|
|
|
@ -95,10 +95,12 @@ stnode_clear(stnode_t *node)
|
|||
node->repr_debug = NULL;
|
||||
g_free(node->repr_token);
|
||||
node->repr_token = NULL;
|
||||
node->location.col_start = -1;
|
||||
node->location.col_len = 0;
|
||||
}
|
||||
|
||||
void
|
||||
stnode_init(stnode_t *node, sttype_id_t type_id, gpointer data, char *token)
|
||||
stnode_init(stnode_t *node, sttype_id_t type_id, gpointer data, char *token, stloc_t *loc)
|
||||
{
|
||||
sttype_t *type;
|
||||
|
||||
|
@ -108,6 +110,13 @@ stnode_init(stnode_t *node, sttype_id_t type_id, gpointer data, char *token)
|
|||
node->repr_display = NULL;
|
||||
node->repr_debug = NULL;
|
||||
node->repr_token = token;
|
||||
if (loc) {
|
||||
node->location = *loc;
|
||||
}
|
||||
else {
|
||||
node->location.col_start = -1;
|
||||
node->location.col_len = 0;
|
||||
}
|
||||
|
||||
if (type_id == STTYPE_UNINITIALIZED) {
|
||||
node->type = NULL;
|
||||
|
@ -131,69 +140,25 @@ stnode_init(stnode_t *node, sttype_id_t type_id, gpointer data, char *token)
|
|||
void
|
||||
stnode_replace(stnode_t *node, sttype_id_t type_id, gpointer data)
|
||||
{
|
||||
char *repr_token = g_strdup(node->repr_token);
|
||||
char *token = g_strdup(node->repr_token);
|
||||
stloc_t loc = node->location;
|
||||
stnode_clear(node);
|
||||
stnode_init(node, type_id, data, NULL);
|
||||
node->repr_token = repr_token;
|
||||
stnode_init(node, type_id, data, token, &loc);
|
||||
}
|
||||
|
||||
stnode_t*
|
||||
stnode_new(sttype_id_t type_id, gpointer data, char *token)
|
||||
stnode_new(sttype_id_t type_id, gpointer data, char *token, stloc_t *loc)
|
||||
{
|
||||
stnode_t *node;
|
||||
|
||||
node = g_new0(stnode_t, 1);
|
||||
node->magic = STNODE_MAGIC;
|
||||
|
||||
stnode_init(node, type_id, data, token);
|
||||
stnode_init(node, type_id, data, token, loc);
|
||||
|
||||
return node;
|
||||
}
|
||||
|
||||
stnode_t *
|
||||
stnode_new_test(test_op_t op, char *token)
|
||||
{
|
||||
stnode_t *node;
|
||||
|
||||
node = stnode_new(STTYPE_TEST, NULL, token);
|
||||
sttype_test_set_op(node, op);
|
||||
return node;
|
||||
}
|
||||
|
||||
stnode_t *
|
||||
stnode_new_math(test_op_t op, char *token)
|
||||
{
|
||||
stnode_t *node;
|
||||
|
||||
node = stnode_new(STTYPE_ARITHMETIC, NULL, token);
|
||||
sttype_test_set_op(node, op);
|
||||
return node;
|
||||
}
|
||||
|
||||
stnode_t *
|
||||
stnode_new_string(const char *str, char *token)
|
||||
{
|
||||
return stnode_new(STTYPE_STRING, g_strdup(str), token);
|
||||
}
|
||||
|
||||
stnode_t *
|
||||
stnode_new_unparsed(const char *str, char *token)
|
||||
{
|
||||
return stnode_new(STTYPE_UNPARSED, g_strdup(str), token);
|
||||
}
|
||||
|
||||
stnode_t *
|
||||
stnode_new_literal(const char *str, char *token)
|
||||
{
|
||||
return stnode_new(STTYPE_LITERAL, g_strdup(str), token);
|
||||
}
|
||||
|
||||
stnode_t *
|
||||
stnode_new_charconst(unsigned long number, char *token)
|
||||
{
|
||||
return stnode_new(STTYPE_CHARCONST, g_memdup2(&number, sizeof(number)), token);
|
||||
}
|
||||
|
||||
stnode_t*
|
||||
stnode_dup(const stnode_t *node)
|
||||
{
|
||||
|
@ -205,6 +170,7 @@ stnode_dup(const stnode_t *node)
|
|||
new->repr_display = NULL;
|
||||
new->repr_debug = NULL;
|
||||
new->repr_token = g_strdup(node->repr_token);
|
||||
new->location = node->location;
|
||||
|
||||
new->type = node->type;
|
||||
if (node->type == NULL)
|
||||
|
@ -268,6 +234,12 @@ stnode_token(stnode_t *node)
|
|||
return node->repr_token;
|
||||
}
|
||||
|
||||
stloc_t *
|
||||
stnode_location(stnode_t *node)
|
||||
{
|
||||
return &node->location;
|
||||
}
|
||||
|
||||
static char *
|
||||
_node_tostr(stnode_t *node, gboolean pretty)
|
||||
{
|
||||
|
|
|
@ -79,6 +79,11 @@ typedef struct {
|
|||
STTypeToStrFunc func_tostr;
|
||||
} sttype_t;
|
||||
|
||||
typedef struct {
|
||||
int col_start;
|
||||
size_t col_len;
|
||||
} stloc_t;
|
||||
|
||||
/** Node (type instance) information */
|
||||
typedef struct {
|
||||
uint32_t magic;
|
||||
|
@ -87,6 +92,7 @@ typedef struct {
|
|||
char *repr_token;
|
||||
char *repr_display;
|
||||
char *repr_debug;
|
||||
stloc_t location;
|
||||
} stnode_t;
|
||||
|
||||
/* These are the sttype_t registration function prototypes. */
|
||||
|
@ -108,25 +114,7 @@ void
|
|||
sttype_register(sttype_t *type);
|
||||
|
||||
stnode_t*
|
||||
stnode_new(sttype_id_t type_id, gpointer data, char *token);
|
||||
|
||||
stnode_t *
|
||||
stnode_new_test(test_op_t op, char *token);
|
||||
|
||||
stnode_t *
|
||||
stnode_new_math(test_op_t op, char *token);
|
||||
|
||||
stnode_t *
|
||||
stnode_new_string(const char *str, char *token);
|
||||
|
||||
stnode_t *
|
||||
stnode_new_unparsed(const char *str, char *token);
|
||||
|
||||
stnode_t *
|
||||
stnode_new_literal(const char *str, char *token);
|
||||
|
||||
stnode_t *
|
||||
stnode_new_charconst(unsigned long number, char *token);
|
||||
stnode_new(sttype_id_t type_id, gpointer data, char *token, stloc_t *loc);
|
||||
|
||||
stnode_t*
|
||||
stnode_dup(const stnode_t *org);
|
||||
|
@ -135,7 +123,7 @@ void
|
|||
stnode_clear(stnode_t *node);
|
||||
|
||||
void
|
||||
stnode_init(stnode_t *node, sttype_id_t type_id, gpointer data, char *token);
|
||||
stnode_init(stnode_t *node, sttype_id_t type_id, gpointer data, char *token, stloc_t *loc);
|
||||
|
||||
void
|
||||
stnode_replace(stnode_t *node, sttype_id_t type_id, gpointer data);
|
||||
|
@ -158,6 +146,9 @@ stnode_steal_data(stnode_t *node);
|
|||
const char *
|
||||
stnode_token(stnode_t *node);
|
||||
|
||||
stloc_t *
|
||||
stnode_location(stnode_t *node);
|
||||
|
||||
const char *
|
||||
stnode_tostr(stnode_t *node, gboolean pretty);
|
||||
|
||||
|
|
|
@ -276,6 +276,7 @@ libwireshark.so.0 libwireshark0 #MINVER#
|
|||
dfilter_compile_real@Base 3.7.0
|
||||
dfilter_deprecated_tokens@Base 1.9.1
|
||||
dfilter_dump@Base 1.9.1
|
||||
dfilter_expand@Base 3.7.0
|
||||
dfilter_free@Base 1.9.1
|
||||
dfilter_load_field_references@Base 3.7.0
|
||||
dfilter_log_full@Base 3.7.0
|
||||
|
|
Loading…
Reference in New Issue