Commit fd9ecebd authored by Роман Донченко's avatar Роман Донченко Committed by Petr Machata

Add a way to force a line to be interpreted as a function prototype

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".
parent 98058fcc
......@@ -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);
......
......@@ -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)
......
......@@ -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
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment