/src/bin/lttng-crash/lttng-crash
/src/bin/lttng-relayd/lttng-relayd
/src/lib/lttng-ctl/lttng-ctl.pc
-/src/common/filter/filter-grammar-test
+/src/common/filter-grammar-test
/src/common/filter/filter-lexer.c
/src/common/filter/filter-parser.c
/src/common/filter/filter-parser.h
return ret;
}
-/* This is defined in enable_events.c. */
-LTTNG_HIDDEN
-int validate_exclusion_list(
- const char *event_name, const char *const *exclusions);
-
/*
* Parse `str` as a log level in domain `domain_type`.
*
goto error;
}
- if (validate_exclusion_list(name,
- (const char **) exclude_names.array.buffer
- .data
-
- ) != 0) {
+ if (validate_exclusion_list(name, &exclude_names) != 0) {
/*
* Assume validate_exclusion_list already prints an
* error message.
static struct lttng_rate_policy *parse_rate_policy(const char *policy_str)
{
- int num_token;
- char **tokens = NULL;
+ int ret;
+ size_t num_token = 0;
+ struct lttng_dynamic_pointer_array tokens;
struct lttng_rate_policy *policy = NULL;
enum lttng_rate_policy_type policy_type;
unsigned long long value;
char *policy_value_str;
assert(policy_str);
+ lttng_dynamic_pointer_array_init(&tokens, NULL);
- /*
- * rate policy fields are separated by ':'.
- */
- tokens = strutils_split(policy_str, ':', 1);
- num_token = strutils_array_of_strings_len(tokens);
+ /* Rate policy fields are separated by ':'. */
+ ret = strutils_split(policy_str, ':', 1, &tokens);
+ if (ret == 0) {
+ num_token = lttng_dynamic_pointer_array_get_count(&tokens);
+ }
/*
* Early sanity check that the number of parameter is exactly 2.
goto end;
}
- policy_type_str = tokens[0];
- policy_value_str = tokens[1];
+ policy_type_str = lttng_dynamic_pointer_array_get_pointer(&tokens, 0);
+ policy_value_str = lttng_dynamic_pointer_array_get_pointer(&tokens, 1);
/* Parse the type. */
if (strcmp(policy_type_str, "once-after") == 0) {
}
end:
- strutils_free_null_terminated_array_of_strings(tokens);
+ lttng_dynamic_pointer_array_reset(&tokens);
return policy;
}
* Mi print exlcusion list
*/
static
-int mi_print_exclusion(char **names)
+int mi_print_exclusion(const struct lttng_dynamic_pointer_array *exclusions)
{
- int i, ret;
- int count = names ? strutils_array_of_strings_len(names) : 0;
+ int ret;
+ size_t i;
+ const size_t count = lttng_dynamic_pointer_array_get_count(exclusions);
assert(writer);
ret = 0;
goto end;
}
+
ret = mi_lttng_writer_open_element(writer, config_element_exclusions);
if (ret) {
goto end;
}
for (i = 0; i < count; i++) {
+ const char *exclusion = lttng_dynamic_pointer_array_get_pointer(
+ exclusions, i);
+
ret = mi_lttng_writer_write_element_string(writer,
- config_element_exclusion, names[i]);
+ config_element_exclusion, exclusion);
if (ret) {
goto end;
}
* Return allocated string for pretty-printing exclusion names.
*/
static
-char *print_exclusions(char **names)
+char *print_exclusions(const struct lttng_dynamic_pointer_array *exclusions)
{
int length = 0;
- int i;
+ size_t i;
const char preamble[] = " excluding ";
char *ret;
- int count = names ? strutils_array_of_strings_len(names) : 0;
+ const size_t count = lttng_dynamic_pointer_array_get_count(exclusions);
if (count == 0) {
return strdup("");
}
- /* calculate total required length */
+ /* Calculate total required length. */
for (i = 0; i < count; i++) {
- length += strlen(names[i]) + 4;
+ const char *exclusion = lttng_dynamic_pointer_array_get_pointer(
+ exclusions, i);
+
+ length += strlen(exclusion) + 4;
}
length += sizeof(preamble);
if (!ret) {
return NULL;
}
+
strncpy(ret, preamble, length);
for (i = 0; i < count; i++) {
+ const char *exclusion = lttng_dynamic_pointer_array_get_pointer(
+ exclusions, i);
+
strcat(ret, "\"");
- strcat(ret, names[i]);
+ strcat(ret, exclusion);
strcat(ret, "\"");
if (i != count - 1) {
strcat(ret, ", ");
return ret;
}
-/*
- * FIXME: find a good place to declare this since add trigger also uses it
- */
-LTTNG_HIDDEN
-int validate_exclusion_list(
- const char *event_name, const char *const *exclusions);
-
-LTTNG_HIDDEN
-int validate_exclusion_list(
- const char *event_name, const char *const *exclusions)
+int validate_exclusion_list(const char *event_name,
+ const struct lttng_dynamic_pointer_array *exclusions)
{
int ret;
* all exclusions are passed to the session daemon.
*/
if (strutils_is_star_at_the_end_only_glob_pattern(event_name)) {
- const char *const *exclusion;
+ size_t i, num_exclusions;
+
+ num_exclusions = lttng_dynamic_pointer_array_get_count(exclusions);
+
+ for (i = 0; i < num_exclusions; i++) {
+ const char *exclusion =
+ lttng_dynamic_pointer_array_get_pointer(
+ exclusions, i);
- for (exclusion = exclusions; *exclusion; exclusion++) {
- if (!strutils_is_star_glob_pattern(*exclusion) ||
- strutils_is_star_at_the_end_only_glob_pattern(*exclusion)) {
- ret = check_exclusion_subsets(event_name, *exclusion);
+ if (!strutils_is_star_glob_pattern(exclusion) ||
+ strutils_is_star_at_the_end_only_glob_pattern(exclusion)) {
+ ret = check_exclusion_subsets(event_name, exclusion);
if (ret) {
goto error;
}
static int create_exclusion_list_and_validate(const char *event_name,
const char *exclusions_arg,
- char ***exclusion_list)
+ struct lttng_dynamic_pointer_array *exclusions)
{
int ret = 0;
- char **exclusions = NULL;
/* Split exclusions. */
- exclusions = strutils_split(exclusions_arg, ',', true);
- if (!exclusions) {
+ ret = strutils_split(exclusions_arg, ',', true, exclusions);
+ if (ret < 0) {
goto error;
}
- if (validate_exclusion_list(event_name, (const char **) exclusions) !=
+ if (validate_exclusion_list(event_name, exclusions) !=
0) {
goto error;
}
- *exclusion_list = exclusions;
-
goto end;
error:
ret = -1;
- strutils_free_null_terminated_array_of_strings(exclusions);
+ lttng_dynamic_pointer_array_reset(exclusions);
end:
return ret;
}
-static void warn_on_truncated_exclusion_names(char * const *exclusion_list,
+static void warn_on_truncated_exclusion_names(const struct lttng_dynamic_pointer_array *exclusions,
int *warn)
{
- char * const *exclusion;
+ size_t i;
+ const size_t num_exclusions = lttng_dynamic_pointer_array_get_count(exclusions);
+
+ for (i = 0; i < num_exclusions; i++) {
+ const char * const exclusion = lttng_dynamic_pointer_array_get_pointer(exclusions, i);
- for (exclusion = exclusion_list; *exclusion; exclusion++) {
- if (strlen(*exclusion) >= LTTNG_SYMBOL_NAME_LEN) {
+ if (strlen(exclusion) >= LTTNG_SYMBOL_NAME_LEN) {
WARN("Event exclusion \"%s\" will be truncated",
- *exclusion);
+ exclusion);
*warn = 1;
}
}
int error_holder = CMD_SUCCESS, warn = 0, error = 0, success = 1;
char *event_name, *channel_name = NULL;
struct lttng_event *ev;
- struct lttng_domain dom;
- char **exclusion_list = NULL;
+ struct lttng_domain dom = {};
+ struct lttng_dynamic_pointer_array exclusions;
struct lttng_userspace_probe_location *uprobe_loc = NULL;
- memset(&dom, 0, sizeof(dom));
+ lttng_dynamic_pointer_array_init(&exclusions, NULL);
ev = lttng_event_create();
if (!ev) {
if (opt_exclude) {
ret = create_exclusion_list_and_validate("*",
- opt_exclude, &exclusion_list);
+ opt_exclude, &exclusions);
if (ret) {
ret = CMD_ERROR;
goto error;
}
ev->exclusion = 1;
- warn_on_truncated_exclusion_names(exclusion_list,
+ warn_on_truncated_exclusion_names(&exclusions,
&warn);
}
if (!opt_filter) {
ret = lttng_enable_event_with_exclusions(handle,
ev, channel_name,
NULL,
- exclusion_list ? strutils_array_of_strings_len(exclusion_list) : 0,
- exclusion_list);
+ lttng_dynamic_pointer_array_get_count(&exclusions),
+ (char **) exclusions.array.buffer.data);
if (ret < 0) {
switch (-ret) {
case LTTNG_ERR_KERN_EVENT_EXIST:
switch (opt_event_type) {
case LTTNG_EVENT_TRACEPOINT:
if (opt_loglevel && dom.type != LTTNG_DOMAIN_KERNEL) {
- char *exclusion_string = print_exclusions(exclusion_list);
+ char *exclusion_string = print_exclusions(&exclusions);
if (!exclusion_string) {
PERROR("Cannot allocate exclusion_string");
opt_loglevel);
free(exclusion_string);
} else {
- char *exclusion_string = print_exclusions(exclusion_list);
+ char *exclusion_string = print_exclusions(&exclusions);
if (!exclusion_string) {
PERROR("Cannot allocate exclusion_string");
break;
case LTTNG_EVENT_ALL:
if (opt_loglevel && dom.type != LTTNG_DOMAIN_KERNEL) {
- char *exclusion_string = print_exclusions(exclusion_list);
+ char *exclusion_string = print_exclusions(&exclusions);
if (!exclusion_string) {
PERROR("Cannot allocate exclusion_string");
opt_loglevel);
free(exclusion_string);
} else {
- char *exclusion_string = print_exclusions(exclusion_list);
+ char *exclusion_string = print_exclusions(&exclusions);
if (!exclusion_string) {
PERROR("Cannot allocate exclusion_string");
if (opt_filter) {
command_ret = lttng_enable_event_with_exclusions(handle, ev, channel_name,
- opt_filter,
- exclusion_list ? strutils_array_of_strings_len(exclusion_list) : 0,
- exclusion_list);
+ opt_filter,
+ lttng_dynamic_pointer_array_get_count(&exclusions),
+ (char **) exclusions.array.buffer.data);
if (command_ret < 0) {
switch (-command_ret) {
case LTTNG_ERR_FILTER_EXIST:
}
/* print exclusion */
- ret = mi_print_exclusion(exclusion_list);
+ ret = mi_print_exclusion(&exclusions);
if (ret) {
ret = CMD_ERROR;
goto error;
ret = CMD_ERROR;
goto error;
}
- /* Free previously allocated items */
- strutils_free_null_terminated_array_of_strings(
- exclusion_list);
- exclusion_list = NULL;
+ /* Free previously allocated items. */
+ lttng_dynamic_pointer_array_reset(&exclusions);
ret = create_exclusion_list_and_validate(
event_name, opt_exclude,
- &exclusion_list);
+ &exclusions);
if (ret) {
ret = CMD_ERROR;
goto error;
}
warn_on_truncated_exclusion_names(
- exclusion_list, &warn);
+ &exclusions, &warn);
}
ev->loglevel_type = opt_loglevel_type;
command_ret = lttng_enable_event_with_exclusions(handle,
ev, channel_name,
NULL,
- exclusion_list ? strutils_array_of_strings_len(exclusion_list) : 0,
- exclusion_list);
- exclusion_string = print_exclusions(exclusion_list);
+ lttng_dynamic_pointer_array_get_count(&exclusions),
+ (char **) exclusions.array.buffer.data);
+ exclusion_string = print_exclusions(&exclusions);
if (!exclusion_string) {
PERROR("Cannot allocate exclusion_string");
error = 1;
command_ret = lttng_enable_event_with_exclusions(handle, ev, channel_name,
opt_filter,
- exclusion_list ? strutils_array_of_strings_len(exclusion_list) : 0,
- exclusion_list);
- exclusion_string = print_exclusions(exclusion_list);
+ lttng_dynamic_pointer_array_get_count(&exclusions),
+ (char **) exclusions.array.buffer.data);
+ exclusion_string = print_exclusions(&exclusions);
if (!exclusion_string) {
PERROR("Cannot allocate exclusion_string");
error = 1;
}
/* print exclusion */
- ret = mi_print_exclusion(exclusion_list);
+ ret = mi_print_exclusion(&exclusions);
if (ret) {
ret = CMD_ERROR;
goto error;
ret = CMD_ERROR;
}
lttng_destroy_handle(handle);
- strutils_free_null_terminated_array_of_strings(exclusion_list);
+ lttng_dynamic_pointer_array_reset(&exclusions);
lttng_userspace_probe_location_destroy(uprobe_loc);
/* Overwrite ret with error_holder if there was an actual error with
struct lttng_userspace_probe_location **probe_location)
{
int ret = CMD_SUCCESS;
- int num_token;
- char **tokens = NULL;
+ size_t num_token = 0;
char *target_path = NULL;
char *unescaped_target_path = NULL;
char *real_target_path = NULL;
char *symbol_name = NULL, *probe_name = NULL, *provider_name = NULL;
struct lttng_userspace_probe_location *probe_location_local = NULL;
struct lttng_userspace_probe_location_lookup_method *lookup_method = NULL;
+ struct lttng_dynamic_pointer_array tokens;
assert(opt);
/*
* userspace probe fields are separated by ':'.
*/
- tokens = strutils_split(opt, ':', 1);
- num_token = strutils_array_of_strings_len(tokens);
+ ret = strutils_split(opt, ':', true, &tokens);
+ if (ret == 0) {
+ num_token = lttng_dynamic_pointer_array_get_count(&tokens);
+ }
/*
* Early sanity check that the number of parameter is between 2 and 4
* std:PATH:PROVIDER_NAME:PROBE_NAME
* PATH:SYMBOL (same behavior as ELF)
*/
- if (num_token < 2 || num_token > 4) {
+ if (ret < 0 || num_token < 2 || num_token > 4) {
ret = CMD_ERROR;
goto end;
}
case 2:
/* When the probe type is omitted we assume ELF for now. */
case 3:
- if (num_token == 3 && strcmp(tokens[0], "elf") == 0) {
- target_path = tokens[1];
- symbol_name = tokens[2];
+ if (num_token == 3 && strcmp(lttng_dynamic_pointer_array_get_pointer(&tokens, 0), "elf") == 0) {
+ target_path = lttng_dynamic_pointer_array_get_pointer(&tokens, 1);
+ symbol_name = lttng_dynamic_pointer_array_get_pointer(&tokens, 2);
} else if (num_token == 2) {
- target_path = tokens[0];
- symbol_name = tokens[1];
+ target_path = lttng_dynamic_pointer_array_get_pointer(&tokens, 0);
+ symbol_name = lttng_dynamic_pointer_array_get_pointer(&tokens, 1);
} else {
ret = CMD_ERROR;
goto end;
}
break;
case 4:
- if (strcmp(tokens[0], "sdt") == 0) {
- target_path = tokens[1];
- provider_name = tokens[2];
- probe_name = tokens[3];
+ if (strcmp(lttng_dynamic_pointer_array_get_pointer(&tokens, 0), "sdt") == 0) {
+ target_path = lttng_dynamic_pointer_array_get_pointer(&tokens, 1);
+ provider_name = lttng_dynamic_pointer_array_get_pointer(&tokens, 2);
+ probe_name = lttng_dynamic_pointer_array_get_pointer(&tokens, 3);
} else {
ret = CMD_ERROR;
goto end;
end:
lttng_userspace_probe_location_destroy(probe_location_local);
lttng_userspace_probe_location_lookup_method_destroy(lookup_method);
- strutils_free_null_terminated_array_of_strings(tokens);
+ lttng_dynamic_pointer_array_reset(&tokens);
/*
* Freeing both char * here makes the error handling simplier. free()
* performs not action if the pointer is NULL.
#define _LTTNG_UTILS_H
#include <popt.h>
-#include "common/argpar/argpar.h"
+#include <common/argpar/argpar.h>
+#include <common/dynamic-array.h>
#include <lttng/lttng.h>
const struct lttng_trace_archive_location *location,
const char *session_name);
+int validate_exclusion_list(const char *event_name,
+ const struct lttng_dynamic_pointer_array *exclusions);
+
#endif /* _LTTNG_UTILS_H */
uri.h \
utils.h
+noinst_PROGRAMS = filter-grammar-test
+filter_grammar_test_SOURCES = filter-grammar-test.c
+filter_grammar_test_LDADD = \
+ libcommon.la
+filter_grammar_test_CFLAGS = -I $(top_builddir)/src/common
+
all-local:
@if [ x"$(srcdir)" != x"$(builddir)" ]; then \
for script in $(EXTRA_DIST); do \
--- /dev/null
+/*
+ * filter-grammar-test.c
+ *
+ * LTTng filter grammar test
+ *
+ * Copyright 2012 Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
+ *
+ * SPDX-License-Identifier: LGPL-2.1-only
+ *
+ */
+
+#include <stdio.h>
+#include <unistd.h>
+#include <string.h>
+#include <stdlib.h>
+#include <assert.h>
+#include <inttypes.h>
+
+#include <common/compat/errno.h>
+#include "common/bytecode/bytecode.h"
+#include "filter/filter-ast.h"
+#include "filter/filter-parser.h"
+
+/* For error.h */
+int lttng_opt_quiet = 1;
+int lttng_opt_verbose;
+int lttng_opt_mi;
+
+int main(int argc, char **argv)
+{
+ struct filter_parser_ctx *ctx;
+ int ret;
+ int print_xml = 0, generate_ir = 0, generate_bytecode = 0,
+ print_bytecode = 0;
+ int argidx;
+
+ for (argidx = 1; argidx < argc; argidx++) {
+ if (strcmp(argv[argidx], "-p") == 0)
+ print_xml = 1;
+ else if (strcmp(argv[argidx], "-i") == 0)
+ generate_ir = 1;
+ else if (strcmp(argv[argidx], "-b") == 0)
+ generate_bytecode = 1;
+ else if (strcmp(argv[argidx], "-d") == 0)
+ filter_parser_debug = 1;
+ else if (strcmp(argv[argidx], "-B") == 0)
+ print_bytecode = 1;
+ }
+
+ /*
+ * Force generate the bytecode if the user asks to print the bytecode
+ * (can't print it without generating it first).
+ */
+ if (print_bytecode) {
+ generate_bytecode = 1;
+ }
+
+ /*
+ * Force generate the IR if the user asks to generate the bytecode
+ * (the bytecode is generated by visiting the IR).
+ */
+ if (generate_bytecode) {
+ generate_ir = 1;
+ }
+
+ ctx = filter_parser_ctx_alloc(stdin);
+ if (!ctx) {
+ fprintf(stderr, "Error allocating parser\n");
+ goto alloc_error;
+ }
+ ret = filter_parser_ctx_append_ast(ctx);
+ if (ret) {
+ fprintf(stderr, "Parse error\n");
+ goto parse_error;
+ }
+ if (print_xml) {
+ ret = filter_visitor_print_xml(ctx, stdout, 0);
+ if (ret) {
+ fflush(stdout);
+ fprintf(stderr, "XML print error\n");
+ goto parse_error;
+ }
+ }
+ if (generate_ir) {
+ printf("Generating IR... ");
+ fflush(stdout);
+ ret = filter_visitor_ir_generate(ctx);
+ if (ret) {
+ fprintf(stderr, "Generate IR error\n");
+ goto parse_error;
+ }
+ printf("done\n");
+
+ printf("Validating IR... ");
+ fflush(stdout);
+ ret = filter_visitor_ir_check_binary_op_nesting(ctx);
+ if (ret) {
+ goto parse_error;
+ }
+ printf("done\n");
+ }
+ if (generate_bytecode) {
+ printf("Generating bytecode... ");
+ fflush(stdout);
+ ret = filter_visitor_bytecode_generate(ctx);
+ if (ret) {
+ fprintf(stderr, "Generate bytecode error\n");
+ goto parse_error;
+ }
+ printf("done\n");
+ printf("Size of bytecode generated: %u bytes.\n",
+ bytecode_get_len(&ctx->bytecode->b));
+ }
+
+ if (print_bytecode) {
+ unsigned int bytecode_len, len, i;
+
+ len = bytecode_get_len(&ctx->bytecode->b);
+ bytecode_len = ctx->bytecode->b.reloc_table_offset;
+ printf("Bytecode:\n");
+ for (i = 0; i < bytecode_len; i++) {
+ printf("0x%X ",
+ ((uint8_t *) ctx->bytecode->b.data)[i]);
+ }
+ printf("\n");
+ printf("Reloc table:\n");
+ for (i = bytecode_len; i < len;) {
+ printf("{ 0x%X, ",
+ *(uint16_t *) &ctx->bytecode->b.data[i]);
+ i += sizeof(uint16_t);
+ printf("%s } ", &((char *) ctx->bytecode->b.data)[i]);
+ i += strlen(&((char *) ctx->bytecode->b.data)[i]) + 1;
+ }
+ printf("\n");
+ }
+
+ filter_bytecode_free(ctx);
+ filter_ir_free(ctx);
+ filter_parser_ctx_free(ctx);
+ return 0;
+
+parse_error:
+ filter_bytecode_free(ctx);
+ filter_ir_free(ctx);
+ filter_parser_ctx_free(ctx);
+alloc_error:
+ exit(EXIT_FAILURE);
+}
AM_CPPFLAGS += -I$(srcdir) -I$(builddir)
-noinst_PROGRAMS = filter-grammar-test
noinst_LTLIBRARIES = libfilter.la
noinst_HEADERS = filter-ast.h \
filter-symbols.h
all-local: filter-lexer.c
endif # HAVE_FLEX
-
-filter_grammar_test_SOURCES = filter-grammar-test.c
-filter_grammar_test_LDADD = \
- libfilter.la \
- ../bytecode/libbytecode.la
+++ /dev/null
-/*
- * filter-grammar-test.c
- *
- * LTTng filter grammar test
- *
- * Copyright 2012 Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
- *
- * SPDX-License-Identifier: LGPL-2.1-only
- *
- */
-
-#include <stdio.h>
-#include <unistd.h>
-#include <string.h>
-#include <stdlib.h>
-#include <assert.h>
-#include <inttypes.h>
-
-#include <common/compat/errno.h>
-#include "common/bytecode/bytecode.h"
-#include "filter-ast.h"
-#include "filter-parser.h"
-
-int main(int argc, char **argv)
-{
- struct filter_parser_ctx *ctx;
- int ret;
- int print_xml = 0, generate_ir = 0, generate_bytecode = 0,
- print_bytecode = 0;
- int argidx;
-
- for (argidx = 1; argidx < argc; argidx++) {
- if (strcmp(argv[argidx], "-p") == 0)
- print_xml = 1;
- else if (strcmp(argv[argidx], "-i") == 0)
- generate_ir = 1;
- else if (strcmp(argv[argidx], "-b") == 0)
- generate_bytecode = 1;
- else if (strcmp(argv[argidx], "-d") == 0)
- filter_parser_debug = 1;
- else if (strcmp(argv[argidx], "-B") == 0)
- print_bytecode = 1;
- }
-
- /*
- * Force generate the bytecode if the user asks to print the bytecode
- * (can't print it without generating it first).
- */
- if (print_bytecode) {
- generate_bytecode = 1;
- }
-
- /*
- * Force generate the IR if the user asks to generate the bytecode
- * (the bytecode is generated by visiting the IR).
- */
- if (generate_bytecode) {
- generate_ir = 1;
- }
-
- ctx = filter_parser_ctx_alloc(stdin);
- if (!ctx) {
- fprintf(stderr, "Error allocating parser\n");
- goto alloc_error;
- }
- ret = filter_parser_ctx_append_ast(ctx);
- if (ret) {
- fprintf(stderr, "Parse error\n");
- goto parse_error;
- }
- if (print_xml) {
- ret = filter_visitor_print_xml(ctx, stdout, 0);
- if (ret) {
- fflush(stdout);
- fprintf(stderr, "XML print error\n");
- goto parse_error;
- }
- }
- if (generate_ir) {
- printf("Generating IR... ");
- fflush(stdout);
- ret = filter_visitor_ir_generate(ctx);
- if (ret) {
- fprintf(stderr, "Generate IR error\n");
- goto parse_error;
- }
- printf("done\n");
-
- printf("Validating IR... ");
- fflush(stdout);
- ret = filter_visitor_ir_check_binary_op_nesting(ctx);
- if (ret) {
- goto parse_error;
- }
- printf("done\n");
- }
- if (generate_bytecode) {
- printf("Generating bytecode... ");
- fflush(stdout);
- ret = filter_visitor_bytecode_generate(ctx);
- if (ret) {
- fprintf(stderr, "Generate bytecode error\n");
- goto parse_error;
- }
- printf("done\n");
- printf("Size of bytecode generated: %u bytes.\n",
- bytecode_get_len(&ctx->bytecode->b));
- }
-
- if (print_bytecode) {
- unsigned int bytecode_len, len, i;
-
- len = bytecode_get_len(&ctx->bytecode->b);
- bytecode_len = ctx->bytecode->b.reloc_table_offset;
- printf("Bytecode:\n");
- for (i = 0; i < bytecode_len; i++) {
- printf("0x%X ",
- ((uint8_t *) ctx->bytecode->b.data)[i]);
- }
- printf("\n");
- printf("Reloc table:\n");
- for (i = bytecode_len; i < len;) {
- printf("{ 0x%X, ",
- *(uint16_t *) &ctx->bytecode->b.data[i]);
- i += sizeof(uint16_t);
- printf("%s } ", &((char *) ctx->bytecode->b.data)[i]);
- i += strlen(&((char *) ctx->bytecode->b.data)[i]) + 1;
- }
- printf("\n");
- }
-
- filter_bytecode_free(ctx);
- filter_ir_free(ctx);
- filter_parser_ctx_free(ctx);
- return 0;
-
-parse_error:
- filter_bytecode_free(ctx);
- filter_ir_free(ctx);
- filter_parser_ctx_free(ctx);
-alloc_error:
- exit(EXIT_FAILURE);
-}
/*
* Splits the input string `input` using the given delimiter `delim`.
*
- * The return value is an allocated null-terminated array of the
- * resulting substrings (also allocated). You can free this array and
- * its content with strutils_free_null_terminated_array_of_strings(). You
- * can get the number of substrings in it with
- * strutils_array_of_strings_len().
+ * The return value is a dynamic pointer array that is assumed to be empty. The
+ * array must be discarded by the caller by invoking
+ * lttng_dynamic_pointer_array_reset().
*
* Empty substrings are part of the result. For example:
*
* `\`
* `hi`
*
- * Returns NULL if there's an error.
+ * Returns -1 if there's an error.
*/
LTTNG_HIDDEN
-char **strutils_split(const char *input, char delim, bool escape_delim)
+int strutils_split(const char *input,
+ char delim,
+ bool escape_delim,
+ struct lttng_dynamic_pointer_array *out_strings)
{
+ int ret;
size_t at;
size_t number_of_substrings = 1;
size_t longest_substring_len = 0;
const char *s;
const char *last;
- char **substrings = NULL;
assert(input);
assert(!(escape_delim && delim == '\\'));
assert(delim != '\0');
+ lttng_dynamic_pointer_array_init(out_strings, free);
/* First pass: count the number of substrings. */
for (s = input, last = input - 1; *s != '\0'; s++) {
longest_substring_len = s - last - 1;
}
- substrings = calloc(number_of_substrings + 1, sizeof(*substrings));
- if (!substrings) {
- goto error;
- }
-
/* Second pass: actually split and copy substrings. */
for (at = 0, s = input; at < number_of_substrings; at++) {
const char *ss;
char *d;
+ char *substring = zmalloc(longest_substring_len + 1);
+
+ if (!substring) {
+ goto error;
+ }
- substrings[at] = zmalloc(longest_substring_len + 1);
- if (!substrings[at]) {
+ ret = lttng_dynamic_pointer_array_add_pointer(
+ out_strings, substring);
+ if (ret) {
+ free(substring);
goto error;
}
* Copy characters to substring until we find the next
* delimiter or the end of the input string.
*/
- for (ss = s, d = substrings[at]; *ss != '\0'; ss++) {
+ for (ss = s, d = substring; *ss != '\0'; ss++) {
if (escape_delim && *ss == '\\') {
if (ss[1] == delim) {
/*
s = ss + 1;
}
+ ret = 0;
goto end;
error:
- strutils_free_null_terminated_array_of_strings(substrings);
- substrings = NULL;
+ ret = -1;
end:
- return substrings;
+ return ret;
}
LTTNG_HIDDEN
#include <stdbool.h>
#include <common/macros.h>
+#include <common/dynamic-array.h>
LTTNG_HIDDEN
void strutils_normalize_star_glob_pattern(char *pattern);
char *strutils_unescape_string(const char *input, char only_char);
LTTNG_HIDDEN
-char **strutils_split(const char *input, char delim, bool escape_delim);
+int strutils_split(const char *input, char delim, bool escape_delim,
+ struct lttng_dynamic_pointer_array *out_strings);
LTTNG_HIDDEN
void strutils_free_null_terminated_array_of_strings(char **array);
/* Number of TAP tests in this file */
#define NUM_TESTS 69
+/* For error.h */
+int lttng_opt_quiet = 1;
+int lttng_opt_verbose;
+int lttng_opt_mi;
+
static void test_one_split(const char *input, char delim, int escape_delim,
...)
{
va_list vl;
- char **substrings;
- char * const *substring;
bool all_ok = true;
+ struct lttng_dynamic_pointer_array strings;
+ int split_ret;
+ size_t i, string_count;
- substrings = strutils_split(input, delim, escape_delim);
- assert(substrings);
+ split_ret = strutils_split(input, delim, escape_delim, &strings);
+ assert(split_ret == 0);
va_start(vl, escape_delim);
- for (substring = substrings; *substring; substring++) {
+ string_count = lttng_dynamic_pointer_array_get_count(&strings);
+
+ for (i = 0; i < string_count; i++) {
const char *expected_substring = va_arg(vl, const char *);
+ const char *substring =
+ lttng_dynamic_pointer_array_get_pointer(
+ &strings, i);
- diag(" got `%s`, expecting `%s`", *substring, expected_substring);
+ diag(" got `%s`, expecting `%s`", substring, expected_substring);
if (!expected_substring) {
all_ok = false;
break;
}
- if (strcmp(*substring, expected_substring) != 0) {
+ if (strcmp(substring, expected_substring) != 0) {
all_ok = false;
break;
}
}
- strutils_free_null_terminated_array_of_strings(substrings);
+ lttng_dynamic_pointer_array_reset(&strings);
va_end(vl);
ok(all_ok, "strutils_split() produces the expected substrings: `%s` (delim. `%c`, escape `%d`)",
- input, delim, escape_delim);
+ input, delim, escape_delim);
}
static void test_split(void)