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(&param);
@@ -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, &param) < 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


_______________________________________________
Ltrace-devel mailing list
[email protected]
http://lists.alioth.debian.org/cgi-bin/mailman/listinfo/ltrace-devel

Reply via email to