aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rwxr-xr-xbootstrap1
m---------gnulib0
-rw-r--r--gnulib.modules1
-rw-r--r--src/Makefile.am5
-rw-r--r--src/parser.c158
-rw-r--r--tests/Makefile.am3
-rw-r--r--tests/struct02.at36
-rw-r--r--tests/struct03.at39
-rw-r--r--tests/struct04.at29
-rw-r--r--tests/testsuite.at5
10 files changed, 252 insertions, 25 deletions
diff --git a/bootstrap b/bootstrap
index 3fa590b..34ea4a1 100755
--- a/bootstrap
+++ b/bootstrap
@@ -107,7 +107,6 @@ tests_base=tests
# Extra files from gnulib, which override files from other sources.
gnulib_extra_files="
$build_aux/install-sh
- $build_aux/missing
$build_aux/mdate-sh
$build_aux/texinfo.tex
$build_aux/depcomp
diff --git a/gnulib b/gnulib
-Subproject 6553be82a4a522e50ece1a430e82a9b1dfd0f47
+Subproject a62cca3ae2de241b79fd8afa3f4c2384efb6d1d
diff --git a/gnulib.modules b/gnulib.modules
index 53c29e8..60a50de 100644
--- a/gnulib.modules
+++ b/gnulib.modules
@@ -11,3 +11,4 @@ gettext-h
gitlog-to-changelog
progname
snprintf
+xalloc
diff --git a/src/Makefile.am b/src/Makefile.am
index f4736d7..a66f42a 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -18,7 +18,6 @@
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
# 02110-1301 USA.
-INCLUDES = -I$(top_srcdir)/gnu -I../ -I../gnu
bin_PROGRAMS = cflow
cflow_SOURCES = \
@@ -40,7 +39,9 @@ cflow_SOURCES = \
localedir = $(datadir)/locale
LDADD=../gnu/libgnu.a @LIBINTL@
-AM_CPPFLAGS=-DLOCALEDIR=\"$(localedir)\"
+AM_CPPFLAGS=\
+ -I$(top_srcdir)/gnu -I../ -I../gnu\
+ -DLOCALEDIR=\"$(localedir)\"
AM_LFLAGS=-dvp
EXTRA_DIST=cflow.rc
diff --git a/src/parser.c b/src/parser.c
index 176d9f2..bdb9e22 100644
--- a/src/parser.c
+++ b/src/parser.c
@@ -1,5 +1,5 @@
/* This file is part of GNU cflow
- Copyright (C) 1997, 2005, 2006, 2007, 2009, 2010, 2011 Sergey Poznyakoff
+ Copyright (C) 1997, 2005, 2006, 2007, 2009, 2010, 2011, 2014 Sergey Poznyakoff
GNU cflow is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -114,6 +114,94 @@ print_token(TOKSTK *tokptr)
}
}
+static char *
+token_type_str(int t)
+{
+ static char buf[80];
+ switch (t) {
+ case 0:
+ return "EOF";
+ case WORD:
+ return "WORD";
+ case LBRACE0:
+ return "'{'";
+ case RBRACE0:
+ return "'}'";
+ case IDENTIFIER:
+ return "IDENTIFIER";
+ case EXTERN:
+ return "EXTERN";
+ case STATIC:
+ return "STATIC";
+ case TYPEDEF:
+ return "TYPEDEF";
+ case STRUCT:
+ return "STRUCT";
+ case MODIFIER:
+ return "MODIFIER";
+ case OP:
+ return "OP";
+ case UNION:
+ return "UNION";
+ case ENUM:
+ return "ENUM";
+ case LBRACE:
+ return "' {'";
+ case RBRACE:
+ return "' }'";
+ case MEMBER_OF:
+ return "MEMBER_OF";
+ case TYPE:
+ return "TYPE";
+ case STRING:
+ return "STRING";
+ case PARM_WRAPPER:
+ return "PARM_WRAPPER";
+ case QUALIFIER:
+ return "QUALIFIER";
+ }
+ if (isprint(t))
+ snprintf(buf, sizeof(buf), "'%c'(%d)", t, t);
+ else
+ snprintf(buf, sizeof(buf), "%d", t);
+ return buf;
+}
+
+static void
+dbgtok(TOKSTK *t, int delim)
+{
+ if (delim)
+ putchar(delim);
+ printf("{ %s ", token_type_str(t->type));
+ if (t->type)
+ printf(", %s, %d ", t->token ? t->token : "NULL", t->line);
+ putchar('}');
+}
+
+static void
+debugtoken(TOKSTK *t, char *fmt, ...)
+{
+ if (debug > 1) {
+ va_list ap;
+ int i;
+
+ if (fmt) {
+ va_start(ap, fmt);
+ vprintf(fmt, ap);
+ va_end(ap);
+ printf(": ");
+ }
+ if (t) {
+ dbgtok(t, 0);
+ printf("; ");
+ }
+ printf("%d: {", curs);
+ for (i = curs; i < tos; i++)
+ dbgtok(token_stack + i, i == curs ? 0 : ',');
+ printf("}\n");
+ }
+}
+
static void
file_error(char *msg, TOKSTK *tokptr)
{
@@ -129,14 +217,45 @@ void
mark(Stackpos pos)
{
pos[0] = curs;
+ if (debug > 2)
+ printf("marking stack at %d\n", curs);
}
void
restore(Stackpos pos)
{
curs = pos[0];
- if (curs)
+ if (curs) {
tok = token_stack[curs-1];
+ debugtoken(&tok, "restored stack");
+ }
+}
+
+void
+tokdel(int beg, int end)
+{
+ if (end >= beg) {
+ if (end < tos)
+ memmove(token_stack + beg, token_stack + end + 1,
+ (end - beg + 1) * sizeof(token_stack[0]));
+ tos -= (end - beg + 1);
+ }
+}
+
+void
+tokins(int pos, int type, int line, char *token)
+{
+ if (++tos == token_stack_length) {
+ token_stack_length += token_stack_increase;
+ token_stack = xrealloc(token_stack,
+ token_stack_length*sizeof(*token_stack));
+ }
+ memmove(token_stack + pos + 1, token_stack + pos,
+ (tos - pos - 1) * sizeof(token_stack[0]));
+ token_stack[pos].type = type;
+ token_stack[pos].token = token;
+ token_stack[pos].line = line;
+ debugtoken(&token_stack[pos], "insert at %d", pos);
}
void
@@ -178,9 +297,11 @@ nexttoken()
if (curs == tos) {
type = get_token();
tokpush(type, line_num, yylval.str);
+ yylval.str = NULL;
}
tok = token_stack[curs];
curs++;
+ debugtoken(&tok, "next token");
return tok.type;
}
@@ -191,10 +312,10 @@ putback()
error(10, 0, _("INTERNAL ERROR: cannot return token to stream"));
curs--;
if (curs > 0) {
- tok.type = token_stack[curs-1].type;
- tok.token = token_stack[curs-1].token;
+ tok = token_stack[curs-1];
} else
tok.type = 0;
+ debugtoken(&tok, "putback");
return tok.type;
}
@@ -405,6 +526,9 @@ is_function()
case MODIFIER:
case STATIC:
case EXTERN:
+ case STRUCT:
+ case UNION:
+ case ENUM:
nexttoken();
continue;
case PARM_WRAPPER:
@@ -551,18 +675,14 @@ fake_struct(Ident *ident)
putback();
skip_struct();
if (tok.type == IDENTIFIER || tok.type == MODIFIER) {
- TOKSTK hold = tok;
+ int pos = curs-1;
restore(sp);
if (ident->type_end == -1) {
/* there was no tag. Insert { ... } */
- tos = curs;
- token_stack[curs].type = IDENTIFIER;
- token_stack[curs].token = "{ ... }";
- tos++;
- } else {
- tos = curs + 1;
+ tokdel(curs, pos - 1);
+ tokins(curs, IDENTIFIER, tok.line, "{ ... }");
+ debugtoken(&tok, "modified stack");
}
- tokpush(hold.type, hold.line, hold.token);
} else if (tok.type == '(')
return 0;
else if (tok.type != ';')
@@ -579,7 +699,7 @@ parse_variable_declaration(Ident *ident, int parm)
mark(sp);
ident->type_end = -1;
- if (tok.type == STRUCT) {
+ if (tok.type == STRUCT || tok.type == UNION) {
if (nexttoken() == IDENTIFIER) {
ident->type_end = tos;
}
@@ -588,18 +708,14 @@ parse_variable_declaration(Ident *ident, int parm)
while (tok.type == MODIFIER || tok.type == QUALIFIER)
nexttoken();
if (tok.type == IDENTIFIER) {
- TOKSTK hold = tok;
+ int pos = curs-1;
restore(sp);
if (ident->type_end == -1) {
/* there was no tag. Insert { ... } */
- tos = curs;
- token_stack[curs].type = IDENTIFIER;
- token_stack[curs].token = "{ ... }";
- tos++;
- } else {
- tos = curs + 1;
+ tokdel(curs, pos - 1);
+ tokins(curs, IDENTIFIER, tok.line, "{ ... }");
+ debugtoken(&tok, "modified stack");
}
- tokpush(hold.type, hold.line, hold.token);
} else {
if (tok.type == ';')
return;
diff --git a/tests/Makefile.am b/tests/Makefile.am
index d31aa35..c3fca96 100644
--- a/tests/Makefile.am
+++ b/tests/Makefile.am
@@ -61,6 +61,9 @@ TESTSUITE_AT = \
static.at\
struct00.at\
struct01.at\
+ struct02.at\
+ struct03.at\
+ struct04.at\
testsuite.at\
version.at
diff --git a/tests/struct02.at b/tests/struct02.at
new file mode 100644
index 0000000..85be0b1
--- /dev/null
+++ b/tests/struct02.at
@@ -0,0 +1,36 @@
+# This file is part of GNU cflow testsuite. -*- Autotest -*-
+# Copyright (C) 2014 Sergey Poznyakoff
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License as
+# published by the Free Software Foundation; either version 3, or (at
+# your option) any later version.
+#
+# This program is distributed in the hope that it will be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+# General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+
+AT_SETUP([ANSI C function returning a struct])
+AT_KEYWORDS([struct struct02 ret-struct])
+
+CFLOW_CHECK(
+struct s *
+foo(int arg)
+{
+ bar();
+}
+int
+main(int argc, char **argv)
+{
+ foo();
+}
+],
+[main() <int main (int argc, char **argv) at prog:7>:
+ foo() <struct s *foo (int arg) at prog:2>:
+ bar()])
+
+AT_CLEANUP
diff --git a/tests/struct03.at b/tests/struct03.at
new file mode 100644
index 0000000..808c7f7
--- /dev/null
+++ b/tests/struct03.at
@@ -0,0 +1,39 @@
+# This file is part of GNU cflow testsuite. -*- Autotest -*-
+# Copyright (C) 2014 Sergey Poznyakoff
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License as
+# published by the Free Software Foundation; either version 3, or (at
+# your option) any later version.
+#
+# This program is distributed in the hope that it will be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+# General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+
+AT_SETUP([K&R C function returning a struct])
+AT_KEYWORDS([struct struct03 ret-struct])
+
+CFLOW_CHECK(
+struct s *
+foo(arg)
+ int arg;
+{
+ bar();
+}
+int
+main(argc, argv)
+ int argc;
+ char **argv;
+{
+ foo();
+}
+],
+[main() <int main (argc, argv) at prog:8>:
+ foo() <struct s *foo (arg) at prog:2>:
+ bar()])
+
+AT_CLEANUP
diff --git a/tests/struct04.at b/tests/struct04.at
new file mode 100644
index 0000000..44ce142
--- /dev/null
+++ b/tests/struct04.at
@@ -0,0 +1,29 @@
+# This file is part of GNU cflow testsuite. -*- Autotest -*-
+# Copyright (C) 2014 Sergey Poznyakoff
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License as
+# published by the Free Software Foundation; either version 3, or (at
+# your option) any later version.
+#
+# This program is distributed in the hope that it will be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+# General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+
+AT_SETUP([struct as argument])
+AT_KEYWORDS([struct struct04 arg-struct])
+
+CFLOW_OPT([-m foo],[
+CFLOW_CHECK([
+int
+foo(struct bar *x)
+{
+}
+],
+[foo() <int foo (struct bar *x) at prog:3>])])
+
+AT_CLEANUP
diff --git a/tests/testsuite.at b/tests/testsuite.at
index 33e907b..83cb3b6 100644
--- a/tests/testsuite.at
+++ b/tests/testsuite.at
@@ -1,5 +1,5 @@
# Process this file with autom4te to create testsuite. -*- Autotest -*-
-# Copyright (C) 2005, 2007, 2010, 2011 Sergey Poznyakoff
+# Copyright (C) 2005, 2007, 2010, 2011, 2014 Sergey Poznyakoff
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License as
@@ -70,5 +70,8 @@ m4_include([multi.at])
m4_include([bartest.at])
m4_include([struct00.at])
m4_include([struct01.at])
+m4_include([struct02.at])
+m4_include([struct03.at])
+m4_include([struct04.at])
# End of testsuite.at

Return to:

Send suggestions and report system problems to the System administrator.