1 # Bison Parser Headers. -*- Autotest -*- 2 3 # Copyright (C) 2001-2002, 2006-2007, 2009-2012 Free Software 4 # Foundation, Inc. 5 6 # This program is free software: you can redistribute it and/or modify 7 # it under the terms of the GNU General Public License as published by 8 # the Free Software Foundation, either version 3 of the License, or 9 # (at your option) any later version. 10 # 11 # This program is distributed in the hope that it will be useful, 12 # but WITHOUT ANY WARRANTY; without even the implied warranty of 13 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 # GNU General Public License for more details. 15 # 16 # You should have received a copy of the GNU General Public License 17 # along with this program. If not, see <http://www.gnu.org/licenses/>. 18 19 AT_BANNER([[Parser Headers.]]) 20 21 22 ## --------------------- ## 23 ## Invalid CPP headers. ## 24 ## --------------------- ## 25 26 # AT_TEST_CPP_GUARD_H(BASE-NAME, [DIRECTIVES]) 27 # -------------------------------------------- 28 # FIXME: Much of this can be covered by calc.at. 29 m4_define([AT_TEST_CPP_GUARD_H], 30 [AT_SETUP([Invalid CPP guards: $2 --defines=$1.h]) 31 AT_BISON_OPTION_PUSHDEFS([$2]) 32 # Possibly create inner directories. 33 dirname=`AS_DIRNAME([$1])` 34 AS_MKDIR_P([$dirname]) 35 36 AT_DATA_GRAMMAR([$1.y], 37 [$2 38 %{ 39 #include <$1.h> 40 ]AT_YYERROR_DECLARE_EXTERN[ 41 ]AT_YYLEX_DECLARE_EXTERN[ 42 %} 43 %% 44 dummy:; 45 %% 46 #include <$1.h> 47 ]) 48 49 AT_BISON_CHECK([--defines=$1.h --output=$1.c $1.y]) 50 51 AT_COMPILE([$1.o], [-I. -c $1.c]) 52 53 AT_BISON_OPTION_POPDEFS 54 AT_CLEANUP 55 ]) 56 57 AT_TEST_CPP_GUARD_H([input/input]) 58 AT_TEST_CPP_GUARD_H([9foo]) 59 AT_TEST_CPP_GUARD_H([input/input], [%glr-parser]) 60 AT_TEST_CPP_GUARD_H([9foo], [%glr-parser]) 61 62 63 64 ## ---------------- ## 65 ## export YYLTYPE. ## 66 ## ---------------- ## 67 68 69 AT_SETUP([export YYLTYPE]) 70 71 AT_DATA_GRAMMAR([input.y], 72 [%locations 73 74 %name-prefix "my_" 75 %{ 76 #include <stdio.h> 77 #include <stdlib.h> 78 79 static int 80 my_lex (void) 81 { 82 return EOF; 83 } 84 85 static void 86 my_error (const char *msg) 87 { 88 fprintf (stderr, "%s\n", msg); 89 } 90 91 %} 92 %% 93 exp:; 94 ]) 95 96 AT_BISON_CHECK([--defines -o input.c input.y]) 97 98 # YYLTYPE should be defined, and MY_LLOC declared. 99 AT_DATA([caller.c], 100 [[#include "input.h" 101 YYLTYPE *my_llocp = &my_lloc; 102 103 int my_parse (void); 104 105 int 106 main (void) 107 { 108 return my_parse (); 109 } 110 ]]) 111 112 # Link and execute, just to make sure everything is fine (and in 113 # particular, that MY_LLOC is indeed defined somewhere). 114 AT_COMPILE([caller.o]) 115 AT_COMPILE([input.o]) 116 AT_COMPILE([caller], [caller.o input.o]) 117 AT_PARSER_CHECK([./caller]) 118 119 AT_CLEANUP 120 121 ## ----------------- ## 122 ## Several parsers. ## 123 ## ----------------- ## 124 125 AT_SETUP([Several parsers]) 126 127 # AT_TEST([PREFIX], [DIRECTIVES]) 128 # ------------------------------- 129 # Generate and compile to *.o. Make sure there is no (allowed) YY* 130 # nor yy* identifiers in the header. Check that headers are 131 # self-contained, and can be compiled by a C++ compiler. 132 m4_pushdef([AT_TEST], 133 [AT_BISON_OPTION_PUSHDEFS([%define api.prefix "$1_" $2]) 134 AT_DATA_GRAMMAR([$1.y], 135 [[%define api.prefix "$1_" 136 $2 137 %error-verbose 138 %union 139 { 140 int integer; 141 } 142 %{ 143 #include <stdio.h> 144 ]AT_YYERROR_DECLARE[ 145 ]AT_YYLEX_DECLARE[ 146 %} 147 %% 148 exp: 149 'x' '1' { printf ("x1\n"); } 150 | 'x' '2' { printf ("x2\n"); } 151 | 'x' '3' { printf ("x3\n"); } 152 | 'x' '4' { printf ("x4\n"); } 153 | 'x' '5' { printf ("x5\n"); } 154 | 'x' '6' { printf ("x6\n"); } 155 | 'x' '7' { printf ("x7\n"); } 156 | 'x' '8' { printf ("x8\n"); } 157 ; 158 159 %% 160 ]AT_YYERROR_DEFINE[ 161 ]AT_YYLEX_DEFINE(["$1"])[ 162 ]]) 163 164 AT_BISON_CHECK([-d -o $1.AT_SKEL_CC_IF([cc], [c]) $1.y]) 165 166 AT_LANG_COMPILE([$1.o]) 167 AT_CHECK([[echo "$1" >>expout]]) 168 169 AT_BISON_OPTION_POPDEFS 170 ])# AT_TEST 171 172 AT_DATA([main.cc], 173 [AT_DATA_SOURCE_PROLOGUE 174 [// If we are compiling with CC=$CXX, then do not load the C headers 175 // inside extern "C", since they were _not_ compiled this way. 176 #if ! CC_IS_CXX 177 extern "C" 178 { 179 #endif 180 #include "x1.h" 181 #include "x2.h" 182 #include "x3.h" 183 #include "x4.h" 184 #include "x6.h" 185 #include "x7.h" 186 #include "x8.h" 187 #if ! CC_IS_CXX 188 } 189 #endif 190 #include "x5.hh" 191 //#include "x6.hh" 192 193 #define RUN(S) \ 194 do { \ 195 int res = S; \ 196 if (res) \ 197 std::cerr << #S": " << res << std::endl; \ 198 } while (false) 199 200 int 201 main (void) 202 { 203 RUN(x1_parse()); 204 RUN(x2_parse()); 205 RUN(x3_parse()); 206 RUN(x4_parse()); 207 x5_::parser p5; 208 RUN(p5.parse()); 209 RUN(x6_parse()); 210 RUN(x7_parse()); 211 RUN(x8_parse()); 212 // x6_::parser p6; 213 // RUN(p6.parse()); 214 return 0; 215 } 216 ]])# main.cc 217 218 AT_TEST([x1], []) 219 AT_TEST([x2], [%locations %debug]) 220 AT_TEST([x3], [%glr-parser]) 221 AT_TEST([x4], [%locations %debug %glr-parser]) 222 AT_TEST([x5], [%locations %debug %language "c++"]) 223 AT_TEST([x6], [%define api.pure]) 224 AT_TEST([x7], [%define api.push-pull both]) 225 AT_TEST([x8], [%define api.pure %define api.push-pull both]) 226 #AT_TEST([x5], [%locations %language "c++" %glr-parser]) 227 228 # Check there is no 'yy' left. 229 # C++ output relies on namespaces and still uses yy a lot. 230 # 231 # Check there is no 'YY' left. 232 # Ignore comments, YYChar (template parameter), YYPARSE_PARAM 233 # (obsolete), YYPUSH_MORE(_DEFINED)? (constant definition), 234 # YY_\w+_INCLUDED (header guards). 235 # 236 # YYDEBUG (not renamed) can be read, but not changed. 237 AT_CHECK([[$PERL -n -0777 -e ' 238 s{/\*.*?\*/}{}gs; 239 s{//.*}{}g; 240 s{\b(YYChar 241 |YYPARSE_PARAM 242 |YYPUSH_MORE(_DEFINED)? 243 |YY_\w+_INCLUDED 244 |YY_NULL 245 |(defined|if)\ YYDEBUG 246 )\b}{}gx; 247 while (/^(.*YY.*)$/gm) 248 { 249 print "$ARGV: invalid exported YY: $1\n"; 250 } 251 if ($ARGV =~ /\.h$/) 252 { 253 while (/^(.*yy.*)$/gm) 254 { 255 print "$ARGV: invalid exported yy: $1\n"; 256 } 257 } 258 ' -- *.hh *.h]]) 259 260 # Check that the headers are self-contained, and protected against 261 # multiple inclusions. While at it, check they are sane for C++. 262 for h in *.h *.hh 263 do 264 # No shell expansion with AT_DATA. 265 cat >$h.cc <<EOF 266 AT_DATA_SOURCE_PROLOGUE 267 #include "$h" 268 #include "$h" 269 EOF 270 AT_COMPILE_CXX([$h.o]) 271 done 272 273 # Do this late, so that other checks have been performed. 274 AT_SKIP_IF_CANNOT_LINK_C_AND_CXX 275 276 AT_COMPILE_CXX([parser], [[x[1-8].o -DCC_IS_CXX=$CC_IS_CXX main.cc]]) 277 AT_PARSER_CHECK([./parser], [0], [[expout]]) 278 279 m4_popdef([AT_TEST]) 280 281 AT_CLEANUP 282