diff options
-rwxr-xr-x | bootstrap | 1 | ||||
m--------- | gnulib | 0 | ||||
-rw-r--r-- | gnulib.modules | 1 | ||||
-rw-r--r-- | src/Makefile.am | 5 | ||||
-rw-r--r-- | src/parser.c | 158 | ||||
-rw-r--r-- | tests/Makefile.am | 3 | ||||
-rw-r--r-- | tests/struct02.at | 36 | ||||
-rw-r--r-- | tests/struct03.at | 39 | ||||
-rw-r--r-- | tests/struct04.at | 29 | ||||
-rw-r--r-- | tests/testsuite.at | 5 |
10 files changed, 252 insertions, 25 deletions
@@ -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 |