xref: /Universal-ctags/Units/parser-systemtap.r/functions.d/input.stp (revision 6bc1a8acb6ee788cfa21a39a8d6b8f4496d53f2b)
1#
2# Taken from /usr/share/systemtap/tapset/regex.stp and registers.stp
3#
4// Regular expression subexpression tapset
5// Copyright (C) 2017 Serhei Makarov
6// Copyright (C) 2013 Red Hat, Inc.
7//
8// This file is part of systemtap, and is free software.  You can
9// redistribute it and/or modify it under the terms of the GNU General
10// Public License (GPL); either version 2, or (at your option) any
11// later version.
12
13%{
14#define STAP_NEED_CONTEXT_SUBEXPRESSION 1
15%}
16
17/**
18 * sfunction matched_str - Return the last matched string.
19 *
20 * Description: returns the string matched by the last successful
21 * use of the =~ regexp matching operator. Returns an error if the
22 * last use of =~ led to a failed match.
23 */
24function matched_str:string() { return matched(0) }
25
26/**
27 * sfunction matched - Return a given matched subexpression.
28 *
29 * @n: index to the subexpression to return. 0 corresponds to the
30 * entire regular expression.
31 *
32 * Description: returns the content of the n'th subexpression of the
33 * last successful use of the =~ regex matching operator. Returns an
34 * empty string if the n'th subexpression was not matched (e.g. due to
35 * alternation). Throws an error if the last use of =~ was a failed
36 * match, or if fewer than n subexpressions are present in the
37 * original regexp.
38 */
39function matched:string(n:long)
40%{ /* pure */ /* unprivileged */ /* pragma:tagged_dfa */
41  int start_ix, end_ix; // indices into tag buffer
42  int start, end, length; // actual coordinate values
43
44  if (!CONTEXT->last_match.result) {
45    snprintf(CONTEXT->error_buffer, sizeof(CONTEXT->error_buffer),
46             "Attempted to get subexpression %lld from failed match", (long long) STAP_ARG_n);
47    CONTEXT->last_error = CONTEXT->error_buffer;
48  }
49
50  start_ix = 2 * STAP_ARG_n, end_ix = start_ix + 1;
51
52  if (end_ix >= CONTEXT->last_match.num_final_tags) {
53    snprintf(CONTEXT->error_buffer, sizeof(CONTEXT->error_buffer),
54             "Attempted to get nonexistent subexpression %lld", (long long) STAP_ARG_n);
55    CONTEXT->last_error = CONTEXT->error_buffer;
56  }
57
58  start = CONTEXT->last_match.tag_vals[start_ix];
59  end = CONTEXT->last_match.tag_vals[end_ix];
60  // _stp_printf ("**DEBUG** Extracted subexpression #%lld:(%d,%d) from %d to %d\n", STAP_ARG_n, start_ix, end_ix, start, end);
61
62  if (start < 0 || end < 0) {
63    // If indices are negative, the group was not matched. Return empty string:
64    start = end = 0;
65    // snprintf(CONTEXT->error_buffer, sizeof(CONTEXT->error_buffer),
66    //          "Unknown coordinates for subexpression %lld", STAP_ARG_n);
67    // CONTEXT->last_error = CONTEXT->error_buffer;
68  }
69
70  if (start > end) {
71    // This should not happen.
72    snprintf(CONTEXT->error_buffer, sizeof(CONTEXT->error_buffer),
73             "BUG: inverted coordinates for subexpression %lld", (long long) STAP_ARG_n);
74    CONTEXT->last_error = CONTEXT->error_buffer;
75  }
76
77  length = end - start;
78
79  // TODOXXX assert (start <= strlen(matched_str)) ??
80  // XXX: Must add 1 to length to account for NUL byte in strlcpy().
81  strlcpy(STAP_RETVALUE, CONTEXT->last_match.matched_str + start, length + 1);
82%}
83
84/**
85 * sfunction ngroups - Number of subexpressions in the last match.
86 *
87 * Description: returns the number of subexpressions from the
88 * last successful use of the =~ regex matching operator.
89 *
90 * Note that this number includes subexpressions which are present in
91 * the regex but did not match any string; for example, given the
92 * regex "a|(b)", the subexpressions will count the group for (b)
93 * regardless of whether it matched a string or not. Throws an error
94 * if the last use of =~ was a failed match.
95 */
96function ngroups:long()
97%{ /* pure */ /* unprivileged */ /* pragma:tagged_dfa */
98  if (!CONTEXT->last_match.result) {
99    snprintf(CONTEXT->error_buffer, sizeof(CONTEXT->error_buffer),
100             "Attempted to get subexpression count from failed match");
101    CONTEXT->last_error = CONTEXT->error_buffer;
102  }
103
104  STAP_RETVALUE = CONTEXT->last_match.num_final_tags / 2;
105%}
106
107// XXX: perhaps implement matched_start, matched_end to get indices?
108// XXX: some kind of find-replace functionality?
109// XXX: some kind of splitting / multiple-match functionality?
110
111/*
112 * In nd_syscall.return probes, we sometimes need @entry() values. To
113 * ensure we get the argument in the correct mode, we need a function
114 * that calls asmlinkage() first.
115 */
116function __asmlinkage_int_arg:long(n:long)
117{
118	asmlinkage()
119	return int_arg(n)
120}
121