[Ltrace-devel] [PATCH 2/2] Add a way to force a line to be interpreted as a function prototype
Роман Донченко
dpb at corrigendum.ru
Sun May 10 16:08:18 UTC 2015
Since "import" is not a keyword in C, it might be used as a type name.
However, a function prototype with "import" as the return type would
be interpreted as an import directive. So provide a new keyword,
"function", that can be used to force a line to be interpreted as a
prototype.
Naturally, the new keyword will also work if the return type is
"function" or "typedef".
---
ltrace.conf.5 | 9 +++-
read_config_file.c | 87 ++++++++++++++++++++---------------
testsuite/ltrace.main/parameters2.exp | 22 +++++++++
3 files changed, 79 insertions(+), 39 deletions(-)
diff --git a/ltrace.conf.5 b/ltrace.conf.5
index a0579dc..cca35a5 100644
--- a/ltrace.conf.5
+++ b/ltrace.conf.5
@@ -40,12 +40,17 @@ A prototype describes return type and parameter types of a single
function. The syntax is as follows:
.RS
-\fILENS\fR \fINAME\fR \fB(\fR[\fILENS\fR{,\fILENS\fR}]\fB);\fR
+[\fBfunction\fR] \fILENS\fR \fINAME\fR \fB(\fR[\fILENS\fR{,\fILENS\fR}]\fB);\fR
.RE
\fINAME\fR is the (mangled) name of a symbol. In the elementary case,
\fILENS\fR is simply a type. Both lenses and types are described
-below. For example, a simple function prototype might look like this:
+below. The \fBfunction\fR keyword, if present, has no effect. It can be
+used to force a line to be interpreted as a function prototype when the
+return type is a keyword that would start a different type of line
+(such as \fBimport\fR).
+
+For example, a simple function prototype might look like this:
.RS
.B int\fR kill\fB(int,int);
diff --git a/read_config_file.c b/read_config_file.c
index 336268a..1f1e948 100644
--- a/read_config_file.c
+++ b/read_config_file.c
@@ -1112,27 +1112,9 @@ parse_import(struct protolib_cache *cache, struct protolib *plib,
}
static void
-process_line(struct protolib_cache *cache, struct protolib *plib,
- struct locus *loc, char *buf)
+parse_prototype(struct protolib *plib, struct locus *loc, char **str)
{
- char *str = buf;
-
- debug(3, "Reading line %d of `%s'", loc->line_no, loc->filename);
- skip_whitespace(&str);
-
- /* A comment or empty line. */
- if (*str == ';' || *str == 0 || *str == '\n' || *str == '#')
- return;
-
- if (try_parse_kwd(&str, "import") >= 0) {
- parse_import(cache, plib, loc, &str);
- return;
- }
-
- if (try_parse_kwd(&str, "typedef") >= 0) {
- parse_typedef(plib, loc, &str);
- return;
- }
+ skip_whitespace(str);
struct prototype fun;
prototype_init(&fun);
@@ -1140,7 +1122,7 @@ process_line(struct protolib_cache *cache, struct protolib *plib,
struct param *extra_param = NULL;
char *proto_name = NULL;
int own;
- fun.return_info = parse_lens(plib, loc, &str, NULL, 0, &own, NULL);
+ fun.return_info = parse_lens(plib, loc, str, NULL, 0, &own, NULL);
if (fun.return_info == NULL) {
err:
debug(3, " Skipping line %d", loc->line_no);
@@ -1157,24 +1139,24 @@ process_line(struct protolib_cache *cache, struct protolib *plib,
fun.own_return_info = own;
debug(4, " return_type = %d", fun.return_info->type);
- skip_whitespace(&str);
- proto_name = parse_ident(loc, &str);
+ skip_whitespace(str);
+ proto_name = parse_ident(loc, str);
if (proto_name == NULL)
goto err;
- skip_whitespace(&str);
- if (parse_char(loc, &str, '(') < 0)
+ skip_whitespace(str);
+ if (parse_char(loc, str, '(') < 0)
goto err;
debug(3, " name = %s", proto_name);
int have_stop = 0;
while (1) {
- skip_whitespace(&str);
- if (*str == ')')
+ skip_whitespace(str);
+ if (**str == ')')
break;
- if (str[0] == '+') {
+ if (**str == '+') {
if (have_stop == 0) {
struct param param;
param_init_stop(¶m);
@@ -1187,13 +1169,13 @@ process_line(struct protolib_cache *cache, struct protolib *plib,
}
have_stop = 1;
}
- str++;
+ (*str)++;
}
int own;
size_t param_num = prototype_num_params(&fun) - have_stop;
struct arg_type_info *type
- = parse_lens(plib, loc, &str, &extra_param,
+ = parse_lens(plib, loc, str, &extra_param,
param_num, &own, NULL);
if (type == NULL) {
report_error(loc->filename, loc->line_no,
@@ -1206,17 +1188,17 @@ process_line(struct protolib_cache *cache, struct protolib *plib,
if (prototype_push_param(&fun, ¶m) < 0)
goto oom;
- skip_whitespace(&str);
- if (*str == ',') {
- str++;
+ skip_whitespace(str);
+ if (**str == ',') {
+ (*str)++;
continue;
- } else if (*str == ')') {
+ } else if (**str == ')') {
continue;
} else {
- if (str[strlen(str) - 1] == '\n')
- str[strlen(str) - 1] = '\0';
+ if ((*str)[strlen(*str) - 1] == '\n')
+ (*str)[strlen(*str) - 1] = '\0';
report_error(loc->filename, loc->line_no,
- "syntax error around \"%s\"", str);
+ "syntax error around \"%s\"", *str);
goto err;
}
}
@@ -1260,6 +1242,37 @@ process_line(struct protolib_cache *cache, struct protolib *plib,
}
}
+static void
+process_line(struct protolib_cache *cache, struct protolib *plib,
+ struct locus *loc, char *buf)
+{
+ char *str = buf;
+
+ debug(3, "Reading line %d of `%s'", loc->line_no, loc->filename);
+ skip_whitespace(&str);
+
+ /* A comment or empty line. */
+ if (*str == ';' || *str == 0 || *str == '\n' || *str == '#')
+ return;
+
+ if (try_parse_kwd(&str, "function") >= 0) {
+ parse_prototype(plib, loc, &str);
+ return;
+ }
+
+ if (try_parse_kwd(&str, "import") >= 0) {
+ parse_import(cache, plib, loc, &str);
+ return;
+ }
+
+ if (try_parse_kwd(&str, "typedef") >= 0) {
+ parse_typedef(plib, loc, &str);
+ return;
+ }
+
+ parse_prototype(plib, loc, &str);
+}
+
int
read_config_file(FILE *stream, const char *path,
struct protolib_cache *cache, struct protolib *plib)
diff --git a/testsuite/ltrace.main/parameters2.exp b/testsuite/ltrace.main/parameters2.exp
index 29b332a..dadddc6 100644
--- a/testsuite/ltrace.main/parameters2.exp
+++ b/testsuite/ltrace.main/parameters2.exp
@@ -296,4 +296,26 @@ ltraceMatch1 [ltraceLibTest {
somefunc();
}] {somefunc\(\)} == 1
+# Test that the function keyword works
+
+ltraceMatch [ltraceLibTest {
+ typedef function = int;
+ typedef import = int;
+ typedef typedef = int;
+
+ function function f();
+ function import i();
+ function typedef t();
+} {
+ int f(void);
+ int i(void);
+ int t(void);
+} {
+ int f(void) { return 1; }
+ int i(void) { return 2; }
+ int t(void) { return 3; }
+} {
+ f(); i(); t();
+}] [list [list {f\(\)}] [list {i\(\)}] [list {t\(\)}]]
+
ltraceDone
--
1.8.5.6
More information about the Ltrace-devel
mailing list