aboutsummaryrefslogtreecommitdiff
path: root/options.c
diff options
context:
space:
mode:
authorPetr Machata <pmachata@redhat.com>2012-09-27 23:43:25 +0200
committerPetr Machata <pmachata@redhat.com>2012-10-01 14:18:53 +0200
commit51e74aca71ff7e8be91c074afd4f2264f46294e9 (patch)
tree9d55d829ceef7262f86e0e733eeb3a0fd4d4eaba /options.c
parent74e57dd396818b1a9414c44e397ac82f692f5582 (diff)
downloadltrace-51e74aca71ff7e8be91c074afd4f2264f46294e9.tar.gz
Add parsing of -l option
Diffstat (limited to 'options.c')
-rw-r--r--options.c53
1 files changed, 36 insertions, 17 deletions
diff --git a/options.c b/options.c
index 8b73233..40bac34 100644
--- a/options.c
+++ b/options.c
@@ -74,7 +74,7 @@ usage(void) {
" -F, --config=FILE load alternate configuration file (may be repeated).\n"
" -h, --help display this help and exit.\n"
" -i print instruction pointer at time of library call.\n"
- " -l, --library=FILE print library calls from this library only.\n"
+ " -l, --library=FILE only trace symbols implemented by this library.\n"
" -L do NOT display library calls.\n"
" -n, --indent=NR indent output by NR spaces for each call level nesting.\n"
" -o, --output=FILE write the trace output to that file.\n"
@@ -257,7 +257,7 @@ grok_libname_pattern(char **libnamep, char **libendp)
}
static int
-parse_filter(struct filter *filt, char *expr)
+parse_filter(struct filter *filt, char *expr, int operators)
{
/* Filter is a chain of sym@lib rules separated by '-' or '+'.
* If the filter expression starts with '-', the missing
@@ -266,7 +266,7 @@ parse_filter(struct filter *filt, char *expr)
enum filter_rule_type type = FR_ADD;
while (*expr != 0) {
- size_t s = strcspn(expr, "@-+");
+ size_t s = strcspn(expr, "-+@" + (operators ? 0 : 2));
char *symname = expr;
char *libname;
char *next = expr + s + 1;
@@ -285,7 +285,7 @@ parse_filter(struct filter *filt, char *expr)
} else {
assert(expr[s] == '@');
expr[s] = 0;
- s = strcspn(next, "-+");
+ s = strcspn(next, "-+" + (operators ? 0 : 2));
if (s == 0) {
libname = "*";
expr = next;
@@ -357,7 +357,7 @@ parse_filter(struct filter *filt, char *expr)
}
static struct filter *
-recursive_parse_chain(char *expr)
+recursive_parse_chain(char *expr, int operators)
{
struct filter *filt = malloc(sizeof(*filt));
if (filt == NULL) {
@@ -367,7 +367,7 @@ recursive_parse_chain(char *expr)
}
filter_init(filt);
- if (parse_filter(filt, expr) < 0) {
+ if (parse_filter(filt, expr, operators) < 0) {
fprintf(stderr, "Filter '%s' will be ignored.\n", expr);
free(filt);
filt = NULL;
@@ -376,6 +376,14 @@ recursive_parse_chain(char *expr)
return filt;
}
+static struct filter **
+slist_chase_end(struct filter **begin)
+{
+ for (; *begin != NULL; begin = &(*begin)->next)
+ ;
+ return begin;
+}
+
static void
parse_filter_chain(const char *expr, struct filter **retp)
{
@@ -389,10 +397,7 @@ parse_filter_chain(const char *expr, struct filter **retp)
if (str[0] == '!')
str[0] = '-';
- struct filter **tailp;
- for (tailp = retp; *tailp != NULL; tailp = &(*tailp)->next)
- ;
- *tailp = recursive_parse_chain(str);
+ *slist_chase_end(retp) = recursive_parse_chain(str, 1);
}
char **
@@ -499,10 +504,16 @@ process_options(int argc, char **argv)
case 'i':
opt_i++;
break;
- case 'l':
- // XXX TODO
- fprintf(stderr, "-l support not yet implemented\n");
+
+ case 'l': {
+ size_t patlen = strlen(optarg);
+ char buf[patlen + 2];
+ sprintf(buf, "@%s", optarg);
+ *slist_chase_end(&options.export_filter)
+ = recursive_parse_chain(buf, 0);
break;
+ }
+
case 'L':
libcalls = 0;
break;
@@ -607,13 +618,21 @@ process_options(int argc, char **argv)
opt_F = egg;
}
- /* Set default filter. Use @MAIN for now, as that's what
- * ltrace used to have in the past. XXX Maybe we should make
- * this "*" instead. */
- if (options.plt_filter == NULL && libcalls) {
+ /* If neither -e, nor -l, nor -L are used, set default -e.
+ * Use @MAIN for now, as that's what ltrace used to have in
+ * the past. XXX Maybe we should make this "*" instead. */
+ if (libcalls
+ && options.plt_filter == NULL
+ && options.export_filter == NULL) {
parse_filter_chain("@MAIN", &options.plt_filter);
options.hide_caller = 1;
}
+ if (!libcalls && options.plt_filter != NULL) {
+ fprintf(stderr,
+ "%s: Option -L can't be used with -e or -l.\n",
+ progname);
+ err_usage();
+ }
if (!opt_p && argc < 1) {
fprintf(stderr, "%s: too few arguments\n", progname);